Compare commits
133 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a30878599 | ||
|
|
c8a8935db0 | ||
|
|
ec196f57bb | ||
|
|
f7809ec3a7 | ||
|
|
71d3ec3616 | ||
|
|
4a7cf8d870 | ||
|
|
4bf8836c0a | ||
|
|
1ca36ee29c | ||
|
|
3446ff88cf | ||
|
|
de5a91a13f | ||
|
|
814cd73019 | ||
|
|
c21611661b | ||
|
|
8f817ce689 | ||
|
|
971b5111e7 | ||
|
|
07069a64ae | ||
|
|
6acea51f12 | ||
|
|
7aa2dab307 | ||
|
|
3091be8f67 | ||
|
|
487531cc52 | ||
|
|
58bfcb4273 | ||
|
|
8d8be27f22 | ||
|
|
27a978cba5 | ||
|
|
71b4e6afa4 | ||
|
|
e1f3b19c0c | ||
|
|
649c2aa5a6 | ||
|
|
cac8cc99e1 | ||
|
|
cb162b16f2 | ||
|
|
86e54ce145 | ||
|
|
efd809971f | ||
|
|
38ae14cc4d | ||
|
|
c7e33a90fe | ||
|
|
5add835750 | ||
|
|
734c614cba | ||
|
|
f6b347fa62 | ||
|
|
08d2f3125e | ||
|
|
385c48dcad | ||
|
|
0926057bfe | ||
|
|
6912e3893e | ||
|
|
d3052657df | ||
|
|
a5ca4d8edf | ||
|
|
afb1ebebd5 | ||
|
|
a04a9eb5ad | ||
|
|
027badd21f | ||
|
|
1affc760e6 | ||
|
|
3ca72b7398 | ||
|
|
702dbddd78 | ||
|
|
8fbecc0227 | ||
|
|
421271acfa | ||
|
|
98af76b3ac | ||
|
|
3952fdbe2d | ||
|
|
bc13beaa85 | ||
|
|
59b2e706ca | ||
|
|
8bf835c531 | ||
|
|
087ed7c132 | ||
|
|
4c075df327 | ||
|
|
9ea8baca05 | ||
|
|
9b6784720e | ||
|
|
3761e1dd60 | ||
|
|
b3eb809550 | ||
|
|
cb72865dcc | ||
|
|
d646b4729b | ||
|
|
a2dd903d0d | ||
|
|
28ed378ee7 | ||
|
|
15ae55136f | ||
|
|
b18abd954f | ||
|
|
b45f79a1f8 | ||
|
|
01a03b4c84 | ||
|
|
e48328af34 | ||
|
|
8925d44807 | ||
|
|
213283510f | ||
|
|
9f8190dc28 | ||
|
|
c32d4ee2f7 | ||
|
|
2c867a4b2c | ||
|
|
da5194bdcb | ||
|
|
bbb27aed10 | ||
|
|
c02fbaeae7 | ||
|
|
847218da73 | ||
|
|
90dc788893 | ||
|
|
f3525cc555 | ||
|
|
198f243181 | ||
|
|
8e049f4af5 | ||
|
|
ff465a59b6 | ||
|
|
68b4f3ca04 | ||
|
|
6b31f2b3f2 | ||
|
|
63cf0f1548 | ||
|
|
e607f68b3e | ||
|
|
db3bb82dbd | ||
|
|
5889c600fa | ||
|
|
d7d4c7236c | ||
|
|
f54d8ce36f | ||
|
|
43faa13cb5 | ||
|
|
85a2d994f3 | ||
|
|
d8cd78cd6b | ||
|
|
3e59a5bcd2 | ||
|
|
0efb89d6ff | ||
|
|
6697c075cb | ||
|
|
06660160e7 | ||
|
|
0b571737b7 | ||
|
|
0a486a280d | ||
|
|
bd53e685d0 | ||
|
|
a2bbf3f44e | ||
|
|
410bb62906 | ||
|
|
cbb4ac3e20 | ||
|
|
7508192ab9 | ||
|
|
bbf6cbd8fb | ||
|
|
9765269d27 | ||
|
|
61746b7ff7 | ||
|
|
e6066c2cb5 | ||
|
|
633a918590 | ||
|
|
71c14a0837 | ||
|
|
9bbed2c275 | ||
|
|
d9ba4d9130 | ||
|
|
ecd40de7ec | ||
|
|
e2bd6c06ec | ||
|
|
a26be76d79 | ||
|
|
3b68c1eb69 | ||
|
|
f7879bdbf9 | ||
|
|
dbb0fc519f | ||
|
|
5da89ac05b | ||
|
|
3c785ae7d8 | ||
|
|
d434724a54 | ||
|
|
fc3bf45a7f | ||
|
|
ac0ffab99c | ||
|
|
533f2734f1 | ||
|
|
2859bee4c0 | ||
|
|
972f857c71 | ||
|
|
d2eb1488fd | ||
|
|
508e4eac61 | ||
|
|
fd1d807012 | ||
|
|
906c4c7f39 | ||
|
|
668e43f57c | ||
|
|
6d260c195f | ||
|
|
fdfecbb3f7 |
58
.travis.yml
@@ -1,58 +0,0 @@
|
|||||||
sudo: false
|
|
||||||
language: cpp
|
|
||||||
|
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
- osx
|
|
||||||
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/.cache/yarn
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email: false
|
|
||||||
webhooks:
|
|
||||||
- http://vscode-probot.westus.cloudapp.azure.com:3450/travis/notifications
|
|
||||||
- http://vscode-test-probot.westus.cloudapp.azure.com:3450/travis/notifications
|
|
||||||
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
- ubuntu-toolchain-r-test
|
|
||||||
packages:
|
|
||||||
- gcc-4.9
|
|
||||||
- g++-4.9
|
|
||||||
- gcc-4.9-multilib
|
|
||||||
- g++-4.9-multilib
|
|
||||||
- zip
|
|
||||||
- libgtk2.0-0
|
|
||||||
- libx11-dev
|
|
||||||
- libxkbfile-dev
|
|
||||||
- libsecret-1-dev
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- git submodule update --init --recursive
|
|
||||||
- nvm install 8.9.1
|
|
||||||
- nvm use 8.9.1
|
|
||||||
- npm i -g yarn
|
|
||||||
# - npm config set python `which python`
|
|
||||||
- if [ $TRAVIS_OS_NAME == "linux" ]; then
|
|
||||||
export CXX="g++-4.9" CC="gcc-4.9" DISPLAY=:99.0;
|
|
||||||
sh -e /etc/init.d/xvfb start;
|
|
||||||
sleep 3;
|
|
||||||
fi
|
|
||||||
# Make npm logs less verbose
|
|
||||||
# - npm config set depth 0
|
|
||||||
# - npm config set loglevel warn
|
|
||||||
|
|
||||||
install:
|
|
||||||
- yarn
|
|
||||||
|
|
||||||
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
|
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./scripts/test.sh --coverage --reporter dot; else ./scripts/test.sh --reporter dot; fi
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then node_modules/.bin/coveralls < .build/coverage/lcov.info; fi
|
|
||||||
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
|
||||||
|
|||||||
20
README.md
@@ -1,6 +1,7 @@
|
|||||||
# Azure Data Studio
|
# Azure Data Studio
|
||||||
|
|
||||||
[](https://gitter.im/Microsoft/sqlopsstudio?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](https://gitter.im/Microsoft/sqlopsstudio?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
[](https://dev.azure.com/ms/azuredatastudio/_build/latest?definitionId=4)
|
||||||
|
|
||||||
Azure Data Studio is a data management tool that enables you to work with SQL Server, Azure SQL DB and SQL DW from Windows, macOS and Linux.
|
Azure Data Studio is a data management tool that enables you to work with SQL Server, Azure SQL DB and SQL DW from Windows, macOS and Linux.
|
||||||
|
|
||||||
@@ -8,12 +9,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.
|
||||||
|
|
||||||
@@ -61,6 +62,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`
|
||||||
@@ -103,7 +110,6 @@ We would like to thank all our users who raised issues, and in particular the fo
|
|||||||
* Russian: Andrey Veselov, Anton Fontanov, Anton Savin, Elena Ostrovskaia, Igor Babichev, Maxim Zelensky, Rodion Fedechkin, Tasha T, Vladimir Zyryanov
|
* 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
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ expressly granted herein, whether by implication, estoppel or otherwise.
|
|||||||
jquery-ui: https://github.com/jquery/jquery-ui
|
jquery-ui: https://github.com/jquery/jquery-ui
|
||||||
jquery.event.drag: https://github.com/devongovett/jquery.event.drag
|
jquery.event.drag: https://github.com/devongovett/jquery.event.drag
|
||||||
jschardet: https://github.com/aadsm/jschardet
|
jschardet: https://github.com/aadsm/jschardet
|
||||||
|
JupyterLab: https://github.com/jupyterlab/jupyterlab
|
||||||
make-error: https://github.com/JsCommunity/make-error
|
make-error: https://github.com/JsCommunity/make-error
|
||||||
minimist: https://github.com/substack/minimist
|
minimist: https://github.com/substack/minimist
|
||||||
moment: https://github.com/moment/moment
|
moment: https://github.com/moment/moment
|
||||||
@@ -1166,6 +1167,43 @@ That's all there is to it!
|
|||||||
=========================================
|
=========================================
|
||||||
END OF jschardet NOTICES AND INFORMATION
|
END OF jschardet NOTICES AND INFORMATION
|
||||||
|
|
||||||
|
%% JupyterLab NOTICES AND INFORMATION BEGIN HERE
|
||||||
|
Copyright (c) 2015 Project Jupyter Contributors
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Semver File License
|
||||||
|
===================
|
||||||
|
|
||||||
|
The semver.py file is from https://github.com/podhmo/python-semver
|
||||||
|
which is licensed under the "MIT" license. See the semver.py file for details.
|
||||||
|
|
||||||
|
END OF JupyterLab NOTICES AND INFORMATION
|
||||||
|
|
||||||
%% make-error NOTICES AND INFORMATION BEGIN HERE
|
%% make-error NOTICES AND INFORMATION BEGIN HERE
|
||||||
=========================================
|
=========================================
|
||||||
ISC © Julien Fontanet
|
ISC © Julien Fontanet
|
||||||
|
|||||||
19
appveyor.yml
@@ -1,19 +0,0 @@
|
|||||||
environment:
|
|
||||||
ELECTRON_RUN_AS_NODE: 1
|
|
||||||
VSCODE_BUILD_VERBOSE: true
|
|
||||||
|
|
||||||
cache:
|
|
||||||
- '%LOCALAPPDATA%\Yarn\cache'
|
|
||||||
|
|
||||||
install:
|
|
||||||
- ps: Install-Product node 8.9.1 x64
|
|
||||||
|
|
||||||
build_script:
|
|
||||||
- yarn
|
|
||||||
- .\node_modules\.bin\gulp electron
|
|
||||||
- npm run compile
|
|
||||||
|
|
||||||
test_script:
|
|
||||||
- node --version
|
|
||||||
- .\scripts\test.bat
|
|
||||||
- .\scripts\test-integration.bat
|
|
||||||
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()
|
||||||
26
azure-pipelines-windows.yml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
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 --reporter mocha-junit-reporter
|
||||||
|
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
|
||||||
@@ -129,6 +129,7 @@ const vscodeResources = [
|
|||||||
'out-build/sql/parts/jobManagement/common/media/*.svg',
|
'out-build/sql/parts/jobManagement/common/media/*.svg',
|
||||||
'out-build/sql/media/objectTypes/*.svg',
|
'out-build/sql/media/objectTypes/*.svg',
|
||||||
'out-build/sql/media/icons/*.svg',
|
'out-build/sql/media/icons/*.svg',
|
||||||
|
'out-build/sql/parts/notebook/media/**/*.svg',
|
||||||
'!**/test/**'
|
'!**/test/**'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -9,20 +9,21 @@
|
|||||||
"@types/mime": "0.0.29",
|
"@types/mime": "0.0.29",
|
||||||
"@types/minimatch": "^3.0.3",
|
"@types/minimatch": "^3.0.3",
|
||||||
"@types/node": "8.0.33",
|
"@types/node": "8.0.33",
|
||||||
"@types/xml2js": "0.0.33",
|
|
||||||
"@types/request": "^2.47.0",
|
"@types/request": "^2.47.0",
|
||||||
|
"@types/xml2js": "0.0.33",
|
||||||
"azure-storage": "^2.1.0",
|
"azure-storage": "^2.1.0",
|
||||||
"decompress": "^4.2.0",
|
"decompress": "^4.2.0",
|
||||||
|
"del": "^3.0.0",
|
||||||
"documentdb": "1.13.0",
|
"documentdb": "1.13.0",
|
||||||
"service-downloader": "github:anthonydresser/service-downloader#0.1.5",
|
|
||||||
"fs-extra-promise": "^1.0.1",
|
"fs-extra-promise": "^1.0.1",
|
||||||
|
"github-releases": "^0.4.1",
|
||||||
"mime": "^1.3.4",
|
"mime": "^1.3.4",
|
||||||
"minimist": "^1.2.0",
|
"minimist": "^1.2.0",
|
||||||
|
"request": "^2.85.0",
|
||||||
|
"service-downloader": "github:anthonydresser/service-downloader#0.1.5",
|
||||||
"typescript": "2.9.2",
|
"typescript": "2.9.2",
|
||||||
"vscode": "^1.0.1",
|
"vscode": "^1.0.1",
|
||||||
"xml2js": "^0.4.17",
|
"xml2js": "^0.4.17"
|
||||||
"github-releases": "^0.4.1",
|
|
||||||
"request": "^2.85.0"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"compile": "tsc -p tsconfig.build.json",
|
"compile": "tsc -p tsconfig.build.json",
|
||||||
@@ -30,4 +31,4 @@
|
|||||||
"postinstall": "npm run compile",
|
"postinstall": "npm run compile",
|
||||||
"npmCheckJs": "tsc --noEmit"
|
"npmCheckJs": "tsc --noEmit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,17 +91,17 @@ Filename: "{app}\{#ExeBasename}.exe"; Description: "{cm:LaunchProgram,{#NameLong
|
|||||||
#else
|
#else
|
||||||
#define SoftwareClassesRootKey "HKLM"
|
#define SoftwareClassesRootKey "HKLM"
|
||||||
#endif
|
#endif
|
||||||
Root: HKCR; Subkey: "{#RegValueName}SourceFile"; ValueType: string; ValueName: ""; ValueData: "{cm:SourceFile,{#NameLong}}"; Flags: uninsdeletekey
|
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}SourceFile"; ValueType: string; ValueName: ""; ValueData: "{cm:SourceFile,{#NameLong}}"; Flags: uninsdeletekey
|
||||||
Root: HKCR; Subkey: "{#RegValueName}SourceFile\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\resources\app\resources\win32\code_file.ico"
|
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}SourceFile\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\resources\app\resources\win32\code_file.ico"
|
||||||
Root: HKCR; Subkey: "{#RegValueName}SourceFile\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%1"""
|
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}SourceFile\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%1"""
|
||||||
Root: HKCU; Subkey: "Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};{app}\bin"; Tasks: addtopath; Check: NeedsAddPath(ExpandConstant('{app}\bin'))
|
Root: HKCU; Subkey: "Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};{app}\bin"; Tasks: addtopath; Check: NeedsAddPath(ExpandConstant('{app}\bin'))
|
||||||
|
|
||||||
Root: HKCU; Subkey: "Software\Classes\.sql\OpenWithProgids"; ValueType: none; ValueName: "{#RegValueName}"; Flags: deletevalue uninsdeletevalue; Tasks: associatewithfiles
|
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\.sql\OpenWithProgids"; ValueType: none; ValueName: "{#RegValueName}"; Flags: deletevalue uninsdeletevalue; Tasks: associatewithfiles
|
||||||
Root: HKCU; Subkey: "Software\Classes\.sql\OpenWithProgids"; ValueType: string; ValueName: "{#RegValueName}.sql"; ValueData: ""; Flags: uninsdeletevalue; Tasks: associatewithfiles
|
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\.sql\OpenWithProgids"; ValueType: string; ValueName: "{#RegValueName}.sql"; ValueData: ""; Flags: uninsdeletevalue; Tasks: associatewithfiles
|
||||||
Root: HKCU; Subkey: "Software\Classes\{#RegValueName}.sql"; ValueType: string; ValueName: ""; ValueData: "{cm:SourceFile,SQL}"; Flags: uninsdeletekey; Tasks: associatewithfiles
|
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.sql"; ValueType: string; ValueName: ""; ValueData: "{cm:SourceFile,SQL}"; Flags: uninsdeletekey; Tasks: associatewithfiles
|
||||||
Root: HKCU; Subkey: "Software\Classes\{#RegValueName}.sql"; ValueType: string; ValueName: "AppUserModelID"; ValueData: "{#AppUserId}"; Flags: uninsdeletekey; Tasks: associatewithfiles
|
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.sql"; ValueType: string; ValueName: "AppUserModelID"; ValueData: "{#AppUserId}"; Flags: uninsdeletekey; Tasks: associatewithfiles
|
||||||
Root: HKCU; Subkey: "Software\Classes\{#RegValueName}.sql\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\resources\app\resources\win32\code_file.ico"; Tasks: associatewithfiles
|
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.sql\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\resources\app\resources\win32\code_file.ico"; Tasks: associatewithfiles
|
||||||
Root: HKCU; Subkey: "Software\Classes\{#RegValueName}.sql\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%1"""; Tasks: associatewithfiles
|
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.sql\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%1"""; Tasks: associatewithfiles
|
||||||
; Environment
|
; Environment
|
||||||
#if "user" == InstallTarget
|
#if "user" == InstallTarget
|
||||||
#define EnvironmentRootKey "HKCU"
|
#define EnvironmentRootKey "HKCU"
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
"@types/minimatch@^3.0.3":
|
"@types/minimatch@^3.0.3":
|
||||||
version "3.0.3"
|
version "3.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
|
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
|
||||||
|
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
|
||||||
|
|
||||||
"@types/node@*":
|
"@types/node@*":
|
||||||
version "8.0.51"
|
version "8.0.51"
|
||||||
@@ -570,6 +571,18 @@ deep-assign@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-obj "^1.0.0"
|
is-obj "^1.0.0"
|
||||||
|
|
||||||
|
del@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/del/-/del-3.0.0.tgz#53ecf699ffcbcb39637691ab13baf160819766e5"
|
||||||
|
integrity sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=
|
||||||
|
dependencies:
|
||||||
|
globby "^6.1.0"
|
||||||
|
is-path-cwd "^1.0.0"
|
||||||
|
is-path-in-cwd "^1.0.0"
|
||||||
|
p-map "^1.1.1"
|
||||||
|
pify "^3.0.0"
|
||||||
|
rimraf "^2.2.8"
|
||||||
|
|
||||||
delayed-stream@~1.0.0:
|
delayed-stream@~1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||||
@@ -941,6 +954,29 @@ glob@^5.0.3:
|
|||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
path-is-absolute "^1.0.0"
|
path-is-absolute "^1.0.0"
|
||||||
|
|
||||||
|
glob@^7.0.3:
|
||||||
|
version "7.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
|
||||||
|
integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==
|
||||||
|
dependencies:
|
||||||
|
fs.realpath "^1.0.0"
|
||||||
|
inflight "^1.0.4"
|
||||||
|
inherits "2"
|
||||||
|
minimatch "^3.0.4"
|
||||||
|
once "^1.3.0"
|
||||||
|
path-is-absolute "^1.0.0"
|
||||||
|
|
||||||
|
globby@^6.1.0:
|
||||||
|
version "6.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c"
|
||||||
|
integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=
|
||||||
|
dependencies:
|
||||||
|
array-union "^1.0.1"
|
||||||
|
glob "^7.0.3"
|
||||||
|
object-assign "^4.0.1"
|
||||||
|
pify "^2.0.0"
|
||||||
|
pinkie-promise "^2.0.0"
|
||||||
|
|
||||||
glogg@^1.0.0:
|
glogg@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.1.tgz#dcf758e44789cc3f3d32c1f3562a3676e6a34810"
|
resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.1.tgz#dcf758e44789cc3f3d32c1f3562a3676e6a34810"
|
||||||
@@ -1312,6 +1348,25 @@ is-obj@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
|
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
|
||||||
integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
|
integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
|
||||||
|
|
||||||
|
is-path-cwd@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
|
||||||
|
integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=
|
||||||
|
|
||||||
|
is-path-in-cwd@^1.0.0:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52"
|
||||||
|
integrity sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==
|
||||||
|
dependencies:
|
||||||
|
is-path-inside "^1.0.0"
|
||||||
|
|
||||||
|
is-path-inside@^1.0.0:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036"
|
||||||
|
integrity sha1-jvW33lBDej/cprToZe96pVy0gDY=
|
||||||
|
dependencies:
|
||||||
|
path-is-inside "^1.0.1"
|
||||||
|
|
||||||
is-posix-bracket@^0.1.0:
|
is-posix-bracket@^0.1.0:
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
|
resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
|
||||||
@@ -1777,6 +1832,11 @@ os-tmpdir@~1.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||||
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
|
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
|
||||||
|
|
||||||
|
p-map@^1.1.1:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b"
|
||||||
|
integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==
|
||||||
|
|
||||||
parse-glob@^3.0.4:
|
parse-glob@^3.0.4:
|
||||||
version "3.0.4"
|
version "3.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
|
resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
|
||||||
@@ -1797,6 +1857,11 @@ path-is-absolute@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||||
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
|
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
|
||||||
|
|
||||||
|
path-is-inside@^1.0.1:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
|
||||||
|
integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=
|
||||||
|
|
||||||
pause-stream@0.0.11:
|
pause-stream@0.0.11:
|
||||||
version "0.0.11"
|
version "0.0.11"
|
||||||
resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
|
resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
|
||||||
@@ -1819,7 +1884,7 @@ performance-now@^2.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
||||||
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
||||||
|
|
||||||
pify@^2.3.0:
|
pify@^2.0.0, pify@^2.3.0:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
|
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
|
||||||
integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
|
integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
|
||||||
@@ -2117,7 +2182,7 @@ requires-port@~1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||||
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
|
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
|
||||||
|
|
||||||
rimraf@2:
|
rimraf@2, rimraf@^2.2.8:
|
||||||
version "2.6.2"
|
version "2.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
|
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
|
||||||
integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==
|
integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==
|
||||||
|
|||||||
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.35.0",
|
"version": "0.35.2",
|
||||||
"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",
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ export class JobData implements IAgentDialogData {
|
|||||||
public jobSchedules: sqlops.AgentJobScheduleInfo[];
|
public jobSchedules: sqlops.AgentJobScheduleInfo[];
|
||||||
public alerts: sqlops.AgentAlertInfo[];
|
public alerts: sqlops.AgentAlertInfo[];
|
||||||
public jobId: string;
|
public jobId: string;
|
||||||
|
public startStepId: number;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
ownerUri: string,
|
ownerUri: string,
|
||||||
@@ -60,10 +61,11 @@ export class JobData implements IAgentDialogData {
|
|||||||
this.category = jobInfo.category;
|
this.category = jobInfo.category;
|
||||||
this.description = jobInfo.description;
|
this.description = jobInfo.description;
|
||||||
this.enabled = jobInfo.enabled;
|
this.enabled = jobInfo.enabled;
|
||||||
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;
|
this.jobId = jobInfo.jobId;
|
||||||
|
this.startStepId = jobInfo.startStepId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,17 +143,17 @@ export class JobData implements IAgentDialogData {
|
|||||||
name: this.name,
|
name: this.name,
|
||||||
owner: this.owner,
|
owner: this.owner,
|
||||||
description: this.description,
|
description: this.description,
|
||||||
EmailLevel: this.emailLevel,
|
emailLevel: this.emailLevel,
|
||||||
PageLevel: this.pageLevel,
|
pageLevel: this.pageLevel,
|
||||||
EventLogLevel: this.eventLogLevel,
|
eventLogLevel: this.eventLogLevel,
|
||||||
DeleteLevel: this.deleteLevel,
|
deleteLevel: this.deleteLevel,
|
||||||
OperatorToEmail: this.operatorToEmail,
|
operatorToEmail: this.operatorToEmail,
|
||||||
OperatorToPage: this.operatorToPage,
|
operatorToPage: this.operatorToPage,
|
||||||
enabled: this.enabled,
|
enabled: this.enabled,
|
||||||
category: this.category,
|
category: this.category,
|
||||||
Alerts: this.alerts,
|
alerts: this.alerts,
|
||||||
JobSchedules: this.jobSchedules,
|
jobSchedules: this.jobSchedules,
|
||||||
JobSteps: this.jobSteps,
|
jobSteps: this.jobSteps,
|
||||||
// The properties below are not collected from UI
|
// The properties below are not collected from UI
|
||||||
// We could consider using a seperate class for create job request
|
// We could consider using a seperate class for create job request
|
||||||
//
|
//
|
||||||
@@ -166,7 +168,8 @@ 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: this.jobId
|
jobId: this.jobId,
|
||||||
|
startStepId: this.startStepId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,6 +123,7 @@ export class JobStepData implements IAgentDialogData {
|
|||||||
stepData.retryInterval = jobStepInfo.retryInterval,
|
stepData.retryInterval = jobStepInfo.retryInterval,
|
||||||
stepData.proxyName = jobStepInfo.proxyName;
|
stepData.proxyName = jobStepInfo.proxyName;
|
||||||
stepData.dialogMode = AgentDialogMode.EDIT;
|
stepData.dialogMode = AgentDialogMode.EDIT;
|
||||||
|
stepData.viaJobDialog = true;
|
||||||
return stepData;
|
return stepData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ export abstract class AgentDialog<T extends IAgentDialogData> {
|
|||||||
public readonly onSuccess: vscode.Event<T> = this._onSuccess.event;
|
public readonly onSuccess: vscode.Event<T> = this._onSuccess.event;
|
||||||
public dialog: sqlops.window.modelviewdialog.Dialog;
|
public dialog: sqlops.window.modelviewdialog.Dialog;
|
||||||
|
|
||||||
|
// Dialog Name for Telemetry
|
||||||
|
public dialogName: string;
|
||||||
|
|
||||||
constructor(public ownerUri: string, public model: T, public title: string) {
|
constructor(public ownerUri: string, public model: T, public title: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,8 +34,9 @@ export abstract class AgentDialog<T extends IAgentDialogData> {
|
|||||||
|
|
||||||
protected abstract async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog);
|
protected abstract async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog);
|
||||||
|
|
||||||
public async openDialog() {
|
public async openDialog(dialogName?: string) {
|
||||||
this.dialog = sqlops.window.modelviewdialog.createDialog(this.title);
|
let event = dialogName ? dialogName : null;
|
||||||
|
this.dialog = sqlops.window.modelviewdialog.createDialog(this.title, event);
|
||||||
|
|
||||||
await this.model.initialize();
|
await this.model.initialize();
|
||||||
|
|
||||||
|
|||||||
@@ -116,6 +116,10 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
private static readonly DelayMinutesTextBoxLabel: string = localize('alertDialog.DelayMinutes', 'Delay Minutes');
|
private static readonly DelayMinutesTextBoxLabel: string = localize('alertDialog.DelayMinutes', 'Delay Minutes');
|
||||||
private static readonly DelaySecondsTextBoxLabel: string = localize('alertDialog.DelaySeconds', 'Delay Seconds');
|
private static readonly DelaySecondsTextBoxLabel: string = localize('alertDialog.DelaySeconds', 'Delay Seconds');
|
||||||
|
|
||||||
|
// Event Name strings
|
||||||
|
private readonly NewAlertDialog = 'NewAlertDialogOpen';
|
||||||
|
private readonly EditAlertDialog = 'EditAlertDialogOpened';
|
||||||
|
|
||||||
// UI Components
|
// UI Components
|
||||||
private generalTab: sqlops.window.modelviewdialog.DialogTab;
|
private generalTab: sqlops.window.modelviewdialog.DialogTab;
|
||||||
private responseTab: sqlops.window.modelviewdialog.DialogTab;
|
private responseTab: sqlops.window.modelviewdialog.DialogTab;
|
||||||
@@ -149,6 +153,7 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
private delayMinutesTextBox: sqlops.InputBoxComponent;
|
private delayMinutesTextBox: sqlops.InputBoxComponent;
|
||||||
private delaySecondsTextBox: sqlops.InputBoxComponent;
|
private delaySecondsTextBox: sqlops.InputBoxComponent;
|
||||||
|
|
||||||
|
private isEdit: boolean = false;
|
||||||
private databases: string[];
|
private databases: string[];
|
||||||
private jobModel: JobData;
|
private jobModel: JobData;
|
||||||
public jobId: string;
|
public jobId: string;
|
||||||
@@ -166,6 +171,8 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
this.jobModel = jobModel;
|
this.jobModel = jobModel;
|
||||||
this.jobId = this.jobId ? this.jobId : this.jobModel.jobId;
|
this.jobId = this.jobId ? this.jobId : this.jobModel.jobId;
|
||||||
this.jobName = this.jobName ? this.jobName : this.jobModel.name;
|
this.jobName = this.jobName ? this.jobName : this.jobModel.name;
|
||||||
|
this.isEdit = alertInfo ? true : false;
|
||||||
|
this.dialogName = this.isEdit ? this.EditAlertDialog : this.NewAlertDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
|
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
|
||||||
|
|||||||
@@ -42,11 +42,12 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
private readonly StepsTable_TypeColumnString: string = localize('jobDialog.type', 'Type');
|
private readonly StepsTable_TypeColumnString: string = localize('jobDialog.type', 'Type');
|
||||||
private readonly StepsTable_SuccessColumnString: string = localize('jobDialog.onSuccess', 'On Success');
|
private readonly StepsTable_SuccessColumnString: string = localize('jobDialog.onSuccess', 'On Success');
|
||||||
private readonly StepsTable_FailureColumnString: string = localize('jobDialog.onFailure', 'On Failure');
|
private readonly StepsTable_FailureColumnString: string = localize('jobDialog.onFailure', 'On Failure');
|
||||||
private readonly NewStepButtonString: string = localize('jobDialog.new', 'New...');
|
private readonly NewStepButtonString: string = localize('jobDialog.new', 'New Step');
|
||||||
private readonly EditStepButtonString: string = localize('jobDialog.edit', 'Edit');
|
private readonly EditStepButtonString: string = localize('jobDialog.edit', 'Edit Step');
|
||||||
private readonly DeleteStepButtonString: string = localize('jobDialog.delete', 'Delete');
|
private readonly DeleteStepButtonString: string = localize('jobDialog.delete', 'Delete Step');
|
||||||
private readonly MoveStepUpButtonString: string = localize('jobDialog.moveUp', 'Move Step Up');
|
private readonly MoveStepUpButtonString: string = localize('jobDialog.moveUp', 'Move Step Up');
|
||||||
private readonly MoveStepDownButtonString: string = localize('jobDialog.moveDown', 'Move Step Up');
|
private readonly MoveStepDownButtonString: string = localize('jobDialog.moveDown', 'Move Step Down');
|
||||||
|
private readonly StartStepDropdownString: string = localize('jobDialog.startStepAt', 'Start step');
|
||||||
|
|
||||||
// Notifications tab strings
|
// Notifications tab strings
|
||||||
private readonly NotificationsTabTopLabelString: string = localize('jobDialog.notificationsTabTop', 'Actions to perform when the job completes');
|
private readonly NotificationsTabTopLabelString: string = localize('jobDialog.notificationsTabTop', 'Actions to perform when the job completes');
|
||||||
@@ -67,6 +68,10 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
private readonly AlertEnabledLabelString: string = localize('jobDialog.alertEnabledLabel', 'Enabled');
|
private readonly AlertEnabledLabelString: string = localize('jobDialog.alertEnabledLabel', 'Enabled');
|
||||||
private readonly AlertTypeLabelString: string = localize('jobDialog.alertTypeLabel', 'Type');
|
private readonly AlertTypeLabelString: string = localize('jobDialog.alertTypeLabel', 'Type');
|
||||||
|
|
||||||
|
// Event Name strings
|
||||||
|
private readonly NewJobDialogEvent: string = 'NewJobDialogOpened';
|
||||||
|
private readonly EditJobDialogEvent: string = 'EditJobDialogOpened';
|
||||||
|
|
||||||
// UI Components
|
// UI Components
|
||||||
private generalTab: sqlops.window.modelviewdialog.DialogTab;
|
private generalTab: sqlops.window.modelviewdialog.DialogTab;
|
||||||
private stepsTab: sqlops.window.modelviewdialog.DialogTab;
|
private stepsTab: sqlops.window.modelviewdialog.DialogTab;
|
||||||
@@ -101,6 +106,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
private eventLogConditionDropdown: sqlops.DropDownComponent;
|
private eventLogConditionDropdown: sqlops.DropDownComponent;
|
||||||
private deleteJobCheckBox: sqlops.CheckBoxComponent;
|
private deleteJobCheckBox: sqlops.CheckBoxComponent;
|
||||||
private deleteJobConditionDropdown: sqlops.DropDownComponent;
|
private deleteJobConditionDropdown: sqlops.DropDownComponent;
|
||||||
|
private startStepDropdown: sqlops.DropDownComponent;
|
||||||
|
|
||||||
// Schedule tab controls
|
// Schedule tab controls
|
||||||
private schedulesTable: sqlops.TableComponent;
|
private schedulesTable: sqlops.TableComponent;
|
||||||
@@ -115,6 +121,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
private steps: sqlops.AgentJobStepInfo[];
|
private steps: sqlops.AgentJobStepInfo[];
|
||||||
private schedules: sqlops.AgentJobScheduleInfo[];
|
private schedules: sqlops.AgentJobScheduleInfo[];
|
||||||
private alerts: sqlops.AgentAlertInfo[] = [];
|
private alerts: sqlops.AgentAlertInfo[] = [];
|
||||||
|
private startStepDropdownValues: sqlops.CategoryValue[] = [];
|
||||||
|
|
||||||
constructor(ownerUri: string, jobInfo: sqlops.AgentJobInfo = undefined) {
|
constructor(ownerUri: string, jobInfo: sqlops.AgentJobInfo = undefined) {
|
||||||
super(
|
super(
|
||||||
@@ -125,6 +132,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
this.schedules = this.model.jobSchedules ? this.model.jobSchedules : [];
|
this.schedules = this.model.jobSchedules ? this.model.jobSchedules : [];
|
||||||
this.alerts = this.model.alerts ? this.model.alerts : [];
|
this.alerts = this.model.alerts ? this.model.alerts : [];
|
||||||
this.isEdit = jobInfo ? true : false;
|
this.isEdit = jobInfo ? true : false;
|
||||||
|
this.dialogName = this.isEdit ? this.EditJobDialogEvent : this.NewJobDialogEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async initializeDialog() {
|
protected async initializeDialog() {
|
||||||
@@ -218,19 +226,26 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
this.StepsTable_FailureColumnString
|
this.StepsTable_FailureColumnString
|
||||||
],
|
],
|
||||||
data: data,
|
data: data,
|
||||||
height: 750
|
height: 650
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
|
this.startStepDropdown = view.modelBuilder.dropDown().withProperties({ width: 180 }).component();
|
||||||
|
this.startStepDropdown.enabled = this.steps.length > 1 ? true : false;
|
||||||
|
this.steps.forEach((step) => {
|
||||||
|
this.startStepDropdownValues.push({ displayName: step.id + ': ' + step.stepName, name: step.id.toString() });
|
||||||
|
});
|
||||||
|
this.startStepDropdown.values = this.startStepDropdownValues;
|
||||||
|
|
||||||
this.moveStepUpButton = view.modelBuilder.button()
|
this.moveStepUpButton = view.modelBuilder.button()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
label: this.MoveStepUpButtonString,
|
label: this.MoveStepUpButtonString,
|
||||||
width: 80
|
width: 120
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.moveStepDownButton = view.modelBuilder.button()
|
this.moveStepDownButton = view.modelBuilder.button()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
label: this.MoveStepDownButtonString,
|
label: this.MoveStepDownButtonString,
|
||||||
width: 80
|
width: 120
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.moveStepUpButton.enabled = false;
|
this.moveStepUpButton.enabled = false;
|
||||||
@@ -238,7 +253,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
|
|
||||||
this.newStepButton = view.modelBuilder.button().withProperties({
|
this.newStepButton = view.modelBuilder.button().withProperties({
|
||||||
label: this.NewStepButtonString,
|
label: this.NewStepButtonString,
|
||||||
width: 80
|
width: 140
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
let stepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, null, true);
|
let stepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, null, true);
|
||||||
@@ -246,6 +261,11 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
let stepInfo = JobStepData.convertToAgentJobStepInfo(step);
|
let stepInfo = JobStepData.convertToAgentJobStepInfo(step);
|
||||||
this.steps.push(stepInfo);
|
this.steps.push(stepInfo);
|
||||||
this.stepsTable.data = this.convertStepsToData(this.steps);
|
this.stepsTable.data = this.convertStepsToData(this.steps);
|
||||||
|
this.startStepDropdownValues = [];
|
||||||
|
this.steps.forEach((step) => {
|
||||||
|
this.startStepDropdownValues.push({ displayName: step.id + ': ' + step.stepName, name: step.id.toString() });
|
||||||
|
});
|
||||||
|
this.startStepDropdown.values = this.startStepDropdownValues;
|
||||||
});
|
});
|
||||||
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) {
|
||||||
@@ -258,53 +278,127 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
|
|
||||||
this.editStepButton = view.modelBuilder.button().withProperties({
|
this.editStepButton = view.modelBuilder.button().withProperties({
|
||||||
label: this.EditStepButtonString,
|
label: this.EditStepButtonString,
|
||||||
width: 80
|
width: 140
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.deleteStepButton = view.modelBuilder.button().withProperties({
|
this.deleteStepButton = view.modelBuilder.button().withProperties({
|
||||||
label: this.DeleteStepButtonString,
|
label: this.DeleteStepButtonString,
|
||||||
width: 80
|
width: 140
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.stepsTable.enabled = false;
|
this.stepsTable.enabled = false;
|
||||||
this.editStepButton.enabled = false;
|
this.editStepButton.enabled = false;
|
||||||
this.deleteStepButton.enabled = false;
|
this.deleteStepButton.enabled = false;
|
||||||
|
|
||||||
this.stepsTable.onRowSelected(() => {
|
this.moveStepUpButton.onDidClick(() => {
|
||||||
// only let edit or delete steps if there's
|
let rowNumber = this.stepsTable.selectedRows[0];
|
||||||
// one step selection
|
let previousRow = rowNumber - 1;
|
||||||
|
let previousStep = this.steps[previousRow];
|
||||||
|
let previousStepId = this.steps[previousRow].id;
|
||||||
|
let currentStep = this.steps[rowNumber];
|
||||||
|
let currentStepId = this.steps[rowNumber].id;
|
||||||
|
this.steps[previousRow] = currentStep;
|
||||||
|
this.steps[rowNumber] = previousStep;
|
||||||
|
this.stepsTable.data = this.convertStepsToData(this.steps);
|
||||||
|
this.steps[previousRow].id = previousStepId;
|
||||||
|
this.steps[rowNumber].id = currentStepId;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.moveStepDownButton.onDidClick(() => {
|
||||||
|
let rowNumber = this.stepsTable.selectedRows[0];
|
||||||
|
let nextRow = rowNumber + 1;
|
||||||
|
let nextStep = this.steps[nextRow];
|
||||||
|
let nextStepId = this.steps[nextRow].id;
|
||||||
|
let currentStep = this.steps[rowNumber];
|
||||||
|
let currentStepId = this.steps[rowNumber].id;
|
||||||
|
this.steps[nextRow] = currentStep;
|
||||||
|
this.steps[rowNumber] = nextStep;
|
||||||
|
this.stepsTable.data = this.convertStepsToData(this.steps);
|
||||||
|
this.steps[nextRow].id = nextStepId;
|
||||||
|
this.steps[rowNumber].id = currentStepId;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.editStepButton.onDidClick(() => {
|
||||||
if (this.stepsTable.selectedRows.length === 1) {
|
if (this.stepsTable.selectedRows.length === 1) {
|
||||||
let rowNumber = this.stepsTable.selectedRows[0];
|
let rowNumber = this.stepsTable.selectedRows[0];
|
||||||
let stepData = this.model.jobSteps[rowNumber];
|
let stepData = this.model.jobSteps[rowNumber];
|
||||||
this.deleteStepButton.enabled = true;
|
let editStepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, stepData, true);
|
||||||
this.editStepButton.enabled = true;
|
editStepDialog.onSuccess((step) => {
|
||||||
this.editStepButton.onDidClick(() => {
|
let stepInfo = JobStepData.convertToAgentJobStepInfo(step);
|
||||||
let stepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, stepData, true);
|
for (let i = 0; i < this.steps.length; i++) {
|
||||||
stepDialog.openDialog();
|
if (this.steps[i].id === stepInfo.id) {
|
||||||
});
|
this.steps[i] = stepInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.stepsTable.data = this.convertStepsToData(this.steps);
|
||||||
|
this.startStepDropdownValues = [];
|
||||||
|
this.steps.forEach((step) => {
|
||||||
|
this.startStepDropdownValues.push({ displayName: step.id + ': ' + step.stepName, name: step.id.toString() });
|
||||||
|
});
|
||||||
|
this.startStepDropdown.values = this.startStepDropdownValues;
|
||||||
|
|
||||||
this.deleteStepButton.onDidClick(() => {
|
});
|
||||||
AgentUtils.getAgentService().then((agentService) => {
|
editStepDialog.openDialog();
|
||||||
let steps = this.model.jobSteps ? this.model.jobSteps : [];
|
}
|
||||||
agentService.deleteJobStep(this.ownerUri, stepData).then((result) => {
|
});
|
||||||
if (result && result.success) {
|
|
||||||
delete steps[rowNumber];
|
this.deleteStepButton.onDidClick(() => {
|
||||||
let data = this.convertStepsToData(steps);
|
if (this.stepsTable.selectedRows.length === 1) {
|
||||||
this.stepsTable.data = data;
|
let rowNumber = this.stepsTable.selectedRows[0];
|
||||||
}
|
AgentUtils.getAgentService().then((agentService) => {
|
||||||
});
|
let steps = this.model.jobSteps ? this.model.jobSteps : [];
|
||||||
|
let stepData = this.model.jobSteps[rowNumber];
|
||||||
|
agentService.deleteJobStep(this.ownerUri, stepData).then((result) => {
|
||||||
|
if (result && result.success) {
|
||||||
|
delete steps[rowNumber];
|
||||||
|
let data = this.convertStepsToData(steps);
|
||||||
|
this.stepsTable.data = data;
|
||||||
|
this.startStepDropdownValues = [];
|
||||||
|
this.steps.forEach((step) => {
|
||||||
|
this.startStepDropdownValues.push({ displayName: step.id + ': ' + step.stepName, name: step.id.toString() });
|
||||||
|
});
|
||||||
|
this.startStepDropdown.values = this.startStepDropdownValues;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let formModel = view.modelBuilder.formContainer()
|
this.stepsTable.onRowSelected((row) => {
|
||||||
.withFormItems([{
|
// only let edit or delete steps if there's
|
||||||
|
// one step selection
|
||||||
|
if (this.stepsTable.selectedRows.length === 1) {
|
||||||
|
let rowNumber = this.stepsTable.selectedRows[0];
|
||||||
|
// if it's not the last step
|
||||||
|
if (this.steps.length !== rowNumber + 1) {
|
||||||
|
this.moveStepDownButton.enabled = true;
|
||||||
|
}
|
||||||
|
// if it's not the first step
|
||||||
|
if (rowNumber !== 0) {
|
||||||
|
this.moveStepUpButton.enabled = true;
|
||||||
|
}
|
||||||
|
this.deleteStepButton.enabled = true;
|
||||||
|
this.editStepButton.enabled = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let stepMoveContainer = this.createRowContainer(view).withItems([this.startStepDropdown, this.moveStepUpButton, this.moveStepDownButton]).component();
|
||||||
|
let stepsDialogContainer = this.createRowContainer(view).withItems([this.newStepButton, this.editStepButton, this.deleteStepButton]).component();
|
||||||
|
let formModel = view.modelBuilder.formContainer().withFormItems([
|
||||||
|
{
|
||||||
component: this.stepsTable,
|
component: this.stepsTable,
|
||||||
title: this.JobStepsTopLabelString,
|
title: this.JobStepsTopLabelString
|
||||||
actions: [this.moveStepUpButton, this.moveStepDownButton, this.newStepButton, this.editStepButton, this.deleteStepButton]
|
},
|
||||||
}]).withLayout({ width: '100%' }).component();
|
{
|
||||||
|
component: stepMoveContainer,
|
||||||
|
title: this.StartStepDropdownString
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: stepsDialogContainer,
|
||||||
|
title: ''
|
||||||
|
}
|
||||||
|
]).withLayout({ width: '100%' }).component();
|
||||||
await view.initializeModel(formModel);
|
await view.initializeModel(formModel);
|
||||||
|
this.setConditionDropdownSelectedValue(this.startStepDropdown, this.model.startStepId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -567,6 +661,7 @@ 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);
|
||||||
|
this.model.startStepId = +this.getDropdownValue(this.startStepDropdown);
|
||||||
if (!this.model.jobSteps) {
|
if (!this.model.jobSteps) {
|
||||||
this.model.jobSteps = [];
|
this.model.jobSteps = [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,9 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
private readonly QuitJobReportingSuccess: string = localize('jobStepDialog.quitJobSuccess', 'Quit the job reporting success');
|
private readonly QuitJobReportingSuccess: string = localize('jobStepDialog.quitJobSuccess', 'Quit the job reporting success');
|
||||||
private readonly QuitJobReportingFailure: string = localize('jobStepDialog.quitJobFailure', 'Quit the job reporting failure');
|
private readonly QuitJobReportingFailure: string = localize('jobStepDialog.quitJobFailure', 'Quit the job reporting failure');
|
||||||
|
|
||||||
|
// Event Name strings
|
||||||
|
private readonly NewStepDialog = 'NewStepDialogOpened';
|
||||||
|
private readonly EditStepDialog = 'EditStepDialogOpened';
|
||||||
// UI Components
|
// UI Components
|
||||||
|
|
||||||
// Dialogs
|
// Dialogs
|
||||||
@@ -131,6 +134,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
this.jobModel = jobModel;
|
this.jobModel = jobModel;
|
||||||
this.jobName = this.jobName ? this.jobName : this.jobModel.name;
|
this.jobName = this.jobName ? this.jobName : this.jobModel.name;
|
||||||
this.server = server;
|
this.server = server;
|
||||||
|
this.dialogName = this.isEdit ? this.EditStepDialog : this.NewStepDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeUIComponents() {
|
private initializeUIComponents() {
|
||||||
@@ -519,6 +523,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
this.model.failureAction = this.failureActionDropdown.value as string;
|
this.model.failureAction = this.failureActionDropdown.value as string;
|
||||||
this.model.outputFileName = this.outputFileNameBox.value;
|
this.model.outputFileName = this.outputFileNameBox.value;
|
||||||
this.model.appendToLogFile = this.appendToExistingFileCheckbox.checked;
|
this.model.appendToLogFile = this.appendToExistingFileCheckbox.checked;
|
||||||
|
this.model.command = this.commandTextBox.value ? this.commandTextBox.value : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public async initializeDialog() {
|
public async initializeDialog() {
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
private static readonly AlertEmailColumnLabel: string = localize('createOperator.AlertEmailColumnLabel', 'E-mail');
|
private static readonly AlertEmailColumnLabel: string = localize('createOperator.AlertEmailColumnLabel', 'E-mail');
|
||||||
private static readonly AlertPagerColumnLabel: string = localize('createOperator.AlertPagerColumnLabel', 'Pager');
|
private static readonly AlertPagerColumnLabel: string = localize('createOperator.AlertPagerColumnLabel', 'Pager');
|
||||||
|
|
||||||
|
// Event strings
|
||||||
|
private readonly NewOperatorDialog = 'NewOperatorDialogOpened';
|
||||||
|
private readonly EditOperatorDialog = 'EditOperatorDialogOpened';
|
||||||
|
|
||||||
// UI Components
|
// UI Components
|
||||||
private generalTab: sqlops.window.modelviewdialog.DialogTab;
|
private generalTab: sqlops.window.modelviewdialog.DialogTab;
|
||||||
private notificationsTab: sqlops.window.modelviewdialog.DialogTab;
|
private notificationsTab: sqlops.window.modelviewdialog.DialogTab;
|
||||||
@@ -68,12 +72,15 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
|
|
||||||
// Notification tab controls
|
// Notification tab controls
|
||||||
private alertsTable: sqlops.TableComponent;
|
private alertsTable: sqlops.TableComponent;
|
||||||
|
private isEdit: boolean = false;
|
||||||
|
|
||||||
constructor(ownerUri: string, operatorInfo: sqlops.AgentOperatorInfo = undefined) {
|
constructor(ownerUri: string, operatorInfo: sqlops.AgentOperatorInfo = undefined) {
|
||||||
super(
|
super(
|
||||||
ownerUri,
|
ownerUri,
|
||||||
new OperatorData(ownerUri, operatorInfo),
|
new OperatorData(ownerUri, operatorInfo),
|
||||||
operatorInfo ? OperatorDialog.EditDialogTitle : OperatorDialog.CreateDialogTitle);
|
operatorInfo ? OperatorDialog.EditDialogTitle : OperatorDialog.CreateDialogTitle);
|
||||||
|
this.isEdit = operatorInfo ? true : false;
|
||||||
|
this.dialogName = this.isEdit ? this.EditOperatorDialog : this.NewOperatorDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
|
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ export class ProxyDialog extends AgentDialog<ProxyData> {
|
|||||||
private static readonly PowerShellLabel: string = localize('createProxy.PowerShell', 'PowerShell');
|
private static readonly PowerShellLabel: string = localize('createProxy.PowerShell', 'PowerShell');
|
||||||
private static readonly SubSystemHeadingLabel: string = localize('createProxy.subSystemHeading', 'Active to the following subsytems');
|
private static readonly SubSystemHeadingLabel: string = localize('createProxy.subSystemHeading', 'Active to the following subsytems');
|
||||||
|
|
||||||
|
private readonly NewProxyDialog = 'NewProxyDialogOpened';
|
||||||
|
private readonly EditProxyDialog = 'EditProxyDialogOpened';
|
||||||
|
|
||||||
// UI Components
|
// UI Components
|
||||||
private generalTab: sqlops.window.modelviewdialog.DialogTab;
|
private generalTab: sqlops.window.modelviewdialog.DialogTab;
|
||||||
|
|
||||||
@@ -56,6 +59,7 @@ export class ProxyDialog extends AgentDialog<ProxyData> {
|
|||||||
private powershellCheckBox: sqlops.CheckBoxComponent;
|
private powershellCheckBox: sqlops.CheckBoxComponent;
|
||||||
|
|
||||||
private credentials: sqlops.CredentialInfo[];
|
private credentials: sqlops.CredentialInfo[];
|
||||||
|
private isEdit: boolean = false;
|
||||||
|
|
||||||
constructor(ownerUri: string, proxyInfo: sqlops.AgentProxyInfo = undefined, credentials: sqlops.CredentialInfo[]) {
|
constructor(ownerUri: string, proxyInfo: sqlops.AgentProxyInfo = undefined, credentials: sqlops.CredentialInfo[]) {
|
||||||
super(
|
super(
|
||||||
@@ -63,6 +67,8 @@ export class ProxyDialog extends AgentDialog<ProxyData> {
|
|||||||
new ProxyData(ownerUri, proxyInfo),
|
new ProxyData(ownerUri, proxyInfo),
|
||||||
proxyInfo ? ProxyDialog.EditDialogTitle : ProxyDialog.CreateDialogTitle);
|
proxyInfo ? ProxyDialog.EditDialogTitle : ProxyDialog.CreateDialogTitle);
|
||||||
this.credentials = credentials;
|
this.credentials = credentials;
|
||||||
|
this.isEdit = proxyInfo ? true : false;
|
||||||
|
this.dialogName = this.isEdit ? this.EditProxyDialog : this.NewProxyDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
|
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
|
||||||
|
|||||||
@@ -40,13 +40,13 @@ export class MainController {
|
|||||||
public activate(): void {
|
public activate(): void {
|
||||||
vscode.commands.registerCommand('agent.openJobDialog', (ownerUri: string, jobInfo: sqlops.AgentJobInfo) => {
|
vscode.commands.registerCommand('agent.openJobDialog', (ownerUri: string, jobInfo: sqlops.AgentJobInfo) => {
|
||||||
let dialog = new JobDialog(ownerUri, jobInfo);
|
let dialog = new JobDialog(ownerUri, jobInfo);
|
||||||
dialog.openDialog();
|
dialog.dialogName ? dialog.openDialog(dialog.dialogName) : dialog.openDialog();
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openNewStepDialog', (ownerUri: string, server: string, jobInfo: sqlops.AgentJobInfo, jobStepInfo: sqlops.AgentJobStepInfo) => {
|
vscode.commands.registerCommand('agent.openNewStepDialog', (ownerUri: string, server: string, jobInfo: sqlops.AgentJobInfo, jobStepInfo: sqlops.AgentJobStepInfo) => {
|
||||||
AgentUtils.getAgentService().then((agentService) => {
|
AgentUtils.getAgentService().then((agentService) => {
|
||||||
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
|
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
|
||||||
let dialog = new JobStepDialog(ownerUri, server, jobData, jobStepInfo, false);
|
let dialog = new JobStepDialog(ownerUri, server, jobData, jobStepInfo, false);
|
||||||
dialog.openDialog();
|
dialog.dialogName ? dialog.openDialog(dialog.dialogName) : dialog.openDialog();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openPickScheduleDialog', (ownerUri: string, jobName: string) => {
|
vscode.commands.registerCommand('agent.openPickScheduleDialog', (ownerUri: string, jobName: string) => {
|
||||||
@@ -57,17 +57,16 @@ export class MainController {
|
|||||||
AgentUtils.getAgentService().then((agentService) => {
|
AgentUtils.getAgentService().then((agentService) => {
|
||||||
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
|
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
|
||||||
let dialog = new AlertDialog(ownerUri, jobData, alertInfo, false);
|
let dialog = new AlertDialog(ownerUri, jobData, alertInfo, false);
|
||||||
dialog.openDialog();
|
dialog.dialogName ? dialog.openDialog(dialog.dialogName) : 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);
|
||||||
dialog.openDialog();
|
dialog.dialogName ? dialog.openDialog(dialog.dialogName) : dialog.openDialog();
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openProxyDialog', (ownerUri: string, proxyInfo: sqlops.AgentProxyInfo, credentials: sqlops.CredentialInfo[]) => {
|
vscode.commands.registerCommand('agent.openProxyDialog', (ownerUri: string, proxyInfo: sqlops.AgentProxyInfo, credentials: sqlops.CredentialInfo[]) => {
|
||||||
let dialog = new ProxyDialog(ownerUri, proxyInfo, credentials);
|
let dialog = new ProxyDialog(ownerUri, proxyInfo, credentials);
|
||||||
dialog.openDialog();
|
dialog.dialogName ? dialog.openDialog(dialog.dialogName) : dialog.openDialog();
|
||||||
MainController.showNotYetImplemented();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -147,7 +147,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"request": "2.63.0",
|
"request": "2.88.0",
|
||||||
"azure-arm-resource": "^7.0.0",
|
"azure-arm-resource": "^7.0.0",
|
||||||
"azure-arm-sql": "^5.0.1",
|
"azure-arm-sql": "^5.0.1",
|
||||||
"vscode-nls": "^4.0.0"
|
"vscode-nls": "^4.0.0"
|
||||||
|
|||||||
@@ -69,8 +69,8 @@ export class AzureAccountProvider implements sqlops.AccountProvider {
|
|||||||
return this._tokenCache.clear();
|
return this._tokenCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public getSecurityToken(account: AzureAccount): Thenable<AzureAccountSecurityTokenCollection> {
|
public getSecurityToken(account: AzureAccount, resource: sqlops.AzureResource): Thenable<AzureAccountSecurityTokenCollection> {
|
||||||
return this.doIfInitialized(() => this.getAccessTokens(account));
|
return this.doIfInitialized(() => this.getAccessTokens(account, resource));
|
||||||
}
|
}
|
||||||
|
|
||||||
public initialize(restoredAccounts: sqlops.Account[]): Thenable<sqlops.Account[]> {
|
public initialize(restoredAccounts: sqlops.Account[]): Thenable<sqlops.Account[]> {
|
||||||
@@ -90,7 +90,7 @@ export class AzureAccountProvider implements sqlops.AccountProvider {
|
|||||||
|
|
||||||
// Attempt to get fresh tokens. If this fails then the account is stale.
|
// Attempt to get fresh tokens. If this fails then the account is stale.
|
||||||
// NOTE: Based on ADAL implementation, getting tokens should use the refresh token if necessary
|
// NOTE: Based on ADAL implementation, getting tokens should use the refresh token if necessary
|
||||||
let task = this.getAccessTokens(account)
|
let task = this.getAccessTokens(account, sqlops.AzureResource.ResourceManagement)
|
||||||
.then(
|
.then(
|
||||||
() => {
|
() => {
|
||||||
return account;
|
return account;
|
||||||
@@ -161,9 +161,14 @@ export class AzureAccountProvider implements sqlops.AccountProvider {
|
|||||||
: Promise.reject(localize('accountProviderNotInitialized', 'Account provider not initialized, cannot perform action'));
|
: Promise.reject(localize('accountProviderNotInitialized', 'Account provider not initialized, cannot perform action'));
|
||||||
}
|
}
|
||||||
|
|
||||||
private getAccessTokens(account: AzureAccount): Thenable<AzureAccountSecurityTokenCollection> {
|
private getAccessTokens(account: AzureAccount, resource: sqlops.AzureResource): Thenable<AzureAccountSecurityTokenCollection> {
|
||||||
let self = this;
|
let self = this;
|
||||||
|
|
||||||
|
const resourceIdMap = new Map<sqlops.AzureResource, string>([
|
||||||
|
[sqlops.AzureResource.ResourceManagement, self._metadata.settings.armResource.id],
|
||||||
|
[sqlops.AzureResource.Sql, self._metadata.settings.sqlResource.id]
|
||||||
|
]);
|
||||||
|
|
||||||
let accessTokenPromises: Thenable<void>[] = [];
|
let accessTokenPromises: Thenable<void>[] = [];
|
||||||
let tokenCollection: AzureAccountSecurityTokenCollection = {};
|
let tokenCollection: AzureAccountSecurityTokenCollection = {};
|
||||||
for (let tenant of account.properties.tenants) {
|
for (let tenant of account.properties.tenants) {
|
||||||
@@ -172,7 +177,7 @@ export class AzureAccountProvider implements sqlops.AccountProvider {
|
|||||||
let context = new adal.AuthenticationContext(authorityUrl, null, self._tokenCache);
|
let context = new adal.AuthenticationContext(authorityUrl, null, self._tokenCache);
|
||||||
|
|
||||||
context.acquireToken(
|
context.acquireToken(
|
||||||
self._metadata.settings.armResource.id,
|
resourceIdMap.get(resource),
|
||||||
tenant.userId,
|
tenant.userId,
|
||||||
self._metadata.settings.clientId,
|
self._metadata.settings.clientId,
|
||||||
(error: Error, response: adal.TokenResponse | adal.ErrorResponse) => {
|
(error: Error, response: adal.TokenResponse | adal.ErrorResponse) => {
|
||||||
|
|||||||
@@ -81,6 +81,11 @@ export interface Settings {
|
|||||||
*/
|
*/
|
||||||
armResource?: Resource;
|
armResource?: Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information that describes the SQL Azure resource
|
||||||
|
*/
|
||||||
|
sqlResource?: Resource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of tenant IDs to authenticate against. If defined, then these IDs will be used
|
* A list of tenant IDs to authenticate against. If defined, then these IDs will be used
|
||||||
* instead of querying the tenants endpoint of the armResource
|
* instead of querying the tenants endpoint of the armResource
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ const publicAzureSettings: ProviderSettings = {
|
|||||||
id: 'https://management.core.windows.net/',
|
id: 'https://management.core.windows.net/',
|
||||||
endpoint: 'https://management.azure.com'
|
endpoint: 'https://management.azure.com'
|
||||||
},
|
},
|
||||||
|
sqlResource: {
|
||||||
|
id: 'https://database.windows.net/',
|
||||||
|
endpoint: 'https://database.windows.net'
|
||||||
|
},
|
||||||
redirectUri: 'http://localhost/redirect'
|
redirectUri: 'http://localhost/redirect'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -223,22 +223,16 @@ export default class TokenCache implements adal.TokenCache {
|
|||||||
return this.getOrCreateEncryptionParams()
|
return this.getOrCreateEncryptionParams()
|
||||||
.then(encryptionParams => {
|
.then(encryptionParams => {
|
||||||
try {
|
try {
|
||||||
let cacheCipher = fs.readFileSync(self._cacheSerializationPath, TokenCache.FsOptions);
|
return self.decryptCache('utf8', encryptionParams);
|
||||||
|
|
||||||
let decipher = crypto.createDecipheriv(TokenCache.CipherAlgorithm, encryptionParams.key, encryptionParams.initializationVector);
|
|
||||||
let cacheJson = decipher.update(cacheCipher, 'hex', 'binary');
|
|
||||||
cacheJson += decipher.final('binary');
|
|
||||||
|
|
||||||
// Deserialize the JSON into the array of tokens
|
|
||||||
let cacheObj = <adal.TokenResponse[]>JSON.parse(cacheJson);
|
|
||||||
for (let objIndex in cacheObj) {
|
|
||||||
// Rehydrate Date objects since they will always serialize as a string
|
|
||||||
cacheObj[objIndex].expiresOn = new Date(<string>cacheObj[objIndex].expiresOn);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cacheObj;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw e;
|
try {
|
||||||
|
// try to parse using 'binary' encoding and rewrite cache as UTF8
|
||||||
|
let response = self.decryptCache('binary', encryptionParams);
|
||||||
|
self.writeCache(response);
|
||||||
|
return response;
|
||||||
|
} catch (e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(null, err => {
|
.then(null, err => {
|
||||||
@@ -248,6 +242,22 @@ export default class TokenCache implements adal.TokenCache {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private decryptCache(encoding: crypto.Utf8AsciiBinaryEncoding, encryptionParams: EncryptionParams): adal.TokenResponse[] {
|
||||||
|
let cacheCipher = fs.readFileSync(this._cacheSerializationPath, TokenCache.FsOptions);
|
||||||
|
let decipher = crypto.createDecipheriv(TokenCache.CipherAlgorithm, encryptionParams.key, encryptionParams.initializationVector);
|
||||||
|
let cacheJson = decipher.update(cacheCipher, 'hex', encoding);
|
||||||
|
cacheJson += decipher.final(encoding);
|
||||||
|
|
||||||
|
// Deserialize the JSON into the array of tokens
|
||||||
|
let cacheObj = <adal.TokenResponse[]>JSON.parse(cacheJson);
|
||||||
|
for (let objIndex in cacheObj) {
|
||||||
|
// Rehydrate Date objects since they will always serialize as a string
|
||||||
|
cacheObj[objIndex].expiresOn = new Date(<string>cacheObj[objIndex].expiresOn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cacheObj;
|
||||||
|
}
|
||||||
|
|
||||||
private removeFromCache(cache: adal.TokenResponse[], entries: adal.TokenResponse[]): adal.TokenResponse[] {
|
private removeFromCache(cache: adal.TokenResponse[], entries: adal.TokenResponse[]): adal.TokenResponse[] {
|
||||||
entries.forEach((entry: adal.TokenResponse) => {
|
entries.forEach((entry: adal.TokenResponse) => {
|
||||||
// Check to see if the entry exists
|
// Check to see if the entry exists
|
||||||
@@ -274,7 +284,7 @@ export default class TokenCache implements adal.TokenCache {
|
|||||||
let cacheJson = JSON.stringify(cache);
|
let cacheJson = JSON.stringify(cache);
|
||||||
|
|
||||||
let cipher = crypto.createCipheriv(TokenCache.CipherAlgorithm, encryptionParams.key, encryptionParams.initializationVector);
|
let cipher = crypto.createCipheriv(TokenCache.CipherAlgorithm, encryptionParams.key, encryptionParams.initializationVector);
|
||||||
let cacheCipher = cipher.update(cacheJson, 'binary', 'hex');
|
let cacheCipher = cipher.update(cacheJson, 'utf8', 'hex');
|
||||||
cacheCipher += cipher.final('hex');
|
cacheCipher += cipher.final('hex');
|
||||||
|
|
||||||
fs.writeFileSync(self._cacheSerializationPath, cacheCipher, TokenCache.FsOptions);
|
fs.writeFileSync(self._cacheSerializationPath, cacheCipher, TokenCache.FsOptions);
|
||||||
|
|||||||
@@ -212,8 +212,8 @@ export class ApiWrapper {
|
|||||||
return sqlops.accounts.getAllAccounts();
|
return sqlops.accounts.getAllAccounts();
|
||||||
}
|
}
|
||||||
|
|
||||||
public getSecurityToken(account: sqlops.Account): Thenable<{}> {
|
public getSecurityToken(account: sqlops.Account, resource: sqlops.AzureResource): Thenable<{}> {
|
||||||
return sqlops.accounts.getSecurityToken(account);
|
return sqlops.accounts.getSecurityToken(account, resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly onDidChangeAccounts = sqlops.accounts.onDidChangeAccounts;
|
public readonly onDidChangeAccounts = sqlops.accounts.onDidChangeAccounts;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { window, QuickPickItem } from 'vscode';
|
import { window, QuickPickItem } from 'vscode';
|
||||||
import { IConnectionProfile } from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
import { generateGuid } from './utils';
|
import { generateGuid } from './utils';
|
||||||
import { ApiWrapper } from '../apiWrapper';
|
import { ApiWrapper } from '../apiWrapper';
|
||||||
import { TreeNode } from '../treeNodes';
|
import { TreeNode } from '../treeNodes';
|
||||||
@@ -30,7 +30,7 @@ export function registerAzureResourceCommands(apiWrapper: ApiWrapper, tree: Azur
|
|||||||
|
|
||||||
let subscriptions = await accountNode.getCachedSubscriptions();
|
let subscriptions = await accountNode.getCachedSubscriptions();
|
||||||
if (!subscriptions || subscriptions.length === 0) {
|
if (!subscriptions || subscriptions.length === 0) {
|
||||||
const credentials = await servicePool.credentialService.getCredentials(accountNode.account);
|
const credentials = await servicePool.credentialService.getCredentials(accountNode.account, sqlops.AzureResource.ResourceManagement);
|
||||||
subscriptions = await servicePool.subscriptionService.getSubscriptions(accountNode.account, credentials);
|
subscriptions = await servicePool.subscriptionService.getSubscriptions(accountNode.account, credentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ export function registerAzureResourceCommands(apiWrapper: ApiWrapper, tree: Azur
|
|||||||
});
|
});
|
||||||
|
|
||||||
apiWrapper.registerCommand('azureresource.connectsqldb', async (node?: TreeNode) => {
|
apiWrapper.registerCommand('azureresource.connectsqldb', async (node?: TreeNode) => {
|
||||||
let connectionProfile: IConnectionProfile = {
|
let connectionProfile: sqlops.IConnectionProfile = {
|
||||||
id: generateGuid(),
|
id: generateGuid(),
|
||||||
connectionName: undefined,
|
connectionName: undefined,
|
||||||
serverName: undefined,
|
serverName: undefined,
|
||||||
|
|||||||
@@ -6,29 +6,29 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { ServiceClientCredentials } from 'ms-rest';
|
import { ServiceClientCredentials } from 'ms-rest';
|
||||||
import { Account, DidChangeAccountsParams } from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
import { Event } from 'vscode';
|
import { Event } from 'vscode';
|
||||||
|
|
||||||
import { AzureResourceSubscription, AzureResourceDatabaseServer, AzureResourceDatabase } from './models';
|
import { AzureResourceSubscription, AzureResourceDatabaseServer, AzureResourceDatabase } from './models';
|
||||||
|
|
||||||
export interface IAzureResourceAccountService {
|
export interface IAzureResourceAccountService {
|
||||||
getAccounts(): Promise<Account[]>;
|
getAccounts(): Promise<sqlops.Account[]>;
|
||||||
|
|
||||||
readonly onDidChangeAccounts: Event<DidChangeAccountsParams>;
|
readonly onDidChangeAccounts: Event<sqlops.DidChangeAccountsParams>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IAzureResourceCredentialService {
|
export interface IAzureResourceCredentialService {
|
||||||
getCredentials(account: Account): Promise<ServiceClientCredentials[]>;
|
getCredentials(account: sqlops.Account, resource: sqlops.AzureResource): Promise<ServiceClientCredentials[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IAzureResourceSubscriptionService {
|
export interface IAzureResourceSubscriptionService {
|
||||||
getSubscriptions(account: Account, credentials: ServiceClientCredentials[]): Promise<AzureResourceSubscription[]>;
|
getSubscriptions(account: sqlops.Account, credentials: ServiceClientCredentials[]): Promise<AzureResourceSubscription[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IAzureResourceSubscriptionFilterService {
|
export interface IAzureResourceSubscriptionFilterService {
|
||||||
getSelectedSubscriptions(account: Account): Promise<AzureResourceSubscription[]>;
|
getSelectedSubscriptions(account: sqlops.Account): Promise<AzureResourceSubscription[]>;
|
||||||
|
|
||||||
saveSelectedSubscriptions(account: Account, selectedSubscriptions: AzureResourceSubscription[]): Promise<void>;
|
saveSelectedSubscriptions(account: sqlops.Account, selectedSubscriptions: AzureResourceSubscription[]): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IAzureResourceDatabaseServerService {
|
export interface IAzureResourceDatabaseServerService {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { Account } from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
import { TokenCredentials, ServiceClientCredentials } from 'ms-rest';
|
import { TokenCredentials, ServiceClientCredentials } from 'ms-rest';
|
||||||
import { ApiWrapper } from '../../apiWrapper';
|
import { ApiWrapper } from '../../apiWrapper';
|
||||||
import * as nls from 'vscode-nls';
|
import * as nls from 'vscode-nls';
|
||||||
@@ -21,10 +21,10 @@ export class AzureResourceCredentialService implements IAzureResourceCredentialS
|
|||||||
this._apiWrapper = apiWrapper;
|
this._apiWrapper = apiWrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getCredentials(account: Account): Promise<ServiceClientCredentials[]> {
|
public async getCredentials(account: sqlops.Account, resource: sqlops.AzureResource): Promise<ServiceClientCredentials[]> {
|
||||||
try {
|
try {
|
||||||
let credentials: TokenCredentials[] = [];
|
let credentials: TokenCredentials[] = [];
|
||||||
let tokens = await this._apiWrapper.getSecurityToken(account);
|
let tokens = await this._apiWrapper.getSecurityToken(account, resource);
|
||||||
|
|
||||||
for (let tenant of account.properties.tenants) {
|
for (let tenant of account.properties.tenants) {
|
||||||
let token = tokens[tenant.id].token;
|
let token = tokens[tenant.id].token;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { Account } from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
import { ServiceClientCredentials } from 'ms-rest';
|
import { ServiceClientCredentials } from 'ms-rest';
|
||||||
import { TreeNode } from '../../treeNodes';
|
import { TreeNode } from '../../treeNodes';
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ export abstract class AzureResourceTreeNodeBase extends TreeNode {
|
|||||||
|
|
||||||
export abstract class AzureResourceContainerTreeNodeBase extends AzureResourceTreeNodeBase {
|
export abstract class AzureResourceContainerTreeNodeBase extends AzureResourceTreeNodeBase {
|
||||||
public constructor(
|
public constructor(
|
||||||
public readonly account: Account,
|
public readonly account: sqlops.Account,
|
||||||
treeChangeHandler: IAzureResourceTreeChangeHandler,
|
treeChangeHandler: IAzureResourceTreeChangeHandler,
|
||||||
parent: TreeNode
|
parent: TreeNode
|
||||||
) {
|
) {
|
||||||
@@ -45,7 +45,7 @@ export abstract class AzureResourceContainerTreeNodeBase extends AzureResourceTr
|
|||||||
|
|
||||||
protected async getCredentials(): Promise<ServiceClientCredentials[]> {
|
protected async getCredentials(): Promise<ServiceClientCredentials[]> {
|
||||||
try {
|
try {
|
||||||
return await this.servicePool.credentialService.getCredentials(this.account);
|
return await this.servicePool.credentialService.getCredentials(this.account, sqlops.AzureResource.ResourceManagement);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof AzureResourceCredentialError) {
|
if (error instanceof AzureResourceCredentialError) {
|
||||||
this.servicePool.contextService.showErrorMessage(error.message);
|
this.servicePool.contextService.showErrorMessage(error.message);
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ describe('AzureResourceAccountTreeNode.info', function(): void {
|
|||||||
mockServicePool.subscriptionService = mockSubscriptionService.object;
|
mockServicePool.subscriptionService = mockSubscriptionService.object;
|
||||||
mockServicePool.subscriptionFilterService = mockSubscriptionFilterService.object;
|
mockServicePool.subscriptionFilterService = mockSubscriptionFilterService.object;
|
||||||
|
|
||||||
mockCredentialService.setup((o) => o.getCredentials(mockAccount)).returns(() => Promise.resolve(mockCredentials));
|
mockCredentialService.setup((o) => o.getCredentials(mockAccount, sqlops.AzureResource.ResourceManagement)).returns(() => Promise.resolve(mockCredentials));
|
||||||
mockCacheService.setup((o) => o.get(TypeMoq.It.isAnyString())).returns(() => mockSubscriptionCache);
|
mockCacheService.setup((o) => o.get(TypeMoq.It.isAnyString())).returns(() => mockSubscriptionCache);
|
||||||
mockCacheService.setup((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => mockSubscriptionCache.subscriptions[mockAccount.key.accountId] = mockSubscriptions);
|
mockCacheService.setup((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => mockSubscriptionCache.subscriptions[mockAccount.key.accountId] = mockSubscriptions);
|
||||||
});
|
});
|
||||||
@@ -164,7 +164,7 @@ describe('AzureResourceAccountTreeNode.getChildren', function(): void {
|
|||||||
mockServicePool.subscriptionService = mockSubscriptionService.object;
|
mockServicePool.subscriptionService = mockSubscriptionService.object;
|
||||||
mockServicePool.subscriptionFilterService = mockSubscriptionFilterService.object;
|
mockServicePool.subscriptionFilterService = mockSubscriptionFilterService.object;
|
||||||
|
|
||||||
mockCredentialService.setup((o) => o.getCredentials(mockAccount)).returns(() => Promise.resolve(mockCredentials));
|
mockCredentialService.setup((o) => o.getCredentials(mockAccount, sqlops.AzureResource.ResourceManagement)).returns(() => Promise.resolve(mockCredentials));
|
||||||
mockCacheService.setup((o) => o.get(TypeMoq.It.isAnyString())).returns(() => mockSubscriptionCache);
|
mockCacheService.setup((o) => o.get(TypeMoq.It.isAnyString())).returns(() => mockSubscriptionCache);
|
||||||
mockCacheService.setup((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => mockSubscriptionCache.subscriptions[mockAccount.key.accountId] = mockSubscriptions);
|
mockCacheService.setup((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => mockSubscriptionCache.subscriptions[mockAccount.key.accountId] = mockSubscriptions);
|
||||||
});
|
});
|
||||||
@@ -177,7 +177,7 @@ describe('AzureResourceAccountTreeNode.getChildren', function(): void {
|
|||||||
|
|
||||||
const children = await accountTreeNode.getChildren();
|
const children = await accountTreeNode.getChildren();
|
||||||
|
|
||||||
mockCredentialService.verify((o) => o.getCredentials(mockAccount), TypeMoq.Times.once());
|
mockCredentialService.verify((o) => o.getCredentials(mockAccount, sqlops.AzureResource.ResourceManagement), TypeMoq.Times.once());
|
||||||
mockSubscriptionService.verify((o) => o.getSubscriptions(mockAccount, mockCredentials), TypeMoq.Times.once());
|
mockSubscriptionService.verify((o) => o.getSubscriptions(mockAccount, mockCredentials), TypeMoq.Times.once());
|
||||||
mockCacheService.verify((o) => o.get(TypeMoq.It.isAnyString()), TypeMoq.Times.once());
|
mockCacheService.verify((o) => o.get(TypeMoq.It.isAnyString()), TypeMoq.Times.once());
|
||||||
mockCacheService.verify((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.once());
|
mockCacheService.verify((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||||
@@ -213,7 +213,7 @@ describe('AzureResourceAccountTreeNode.getChildren', function(): void {
|
|||||||
await accountTreeNode.getChildren();
|
await accountTreeNode.getChildren();
|
||||||
const children = await accountTreeNode.getChildren();
|
const children = await accountTreeNode.getChildren();
|
||||||
|
|
||||||
mockCredentialService.verify((o) => o.getCredentials(mockAccount), TypeMoq.Times.exactly(1));
|
mockCredentialService.verify((o) => o.getCredentials(mockAccount, sqlops.AzureResource.ResourceManagement), TypeMoq.Times.exactly(1));
|
||||||
mockSubscriptionService.verify((o) => o.getSubscriptions(mockAccount, mockCredentials), TypeMoq.Times.exactly(1));
|
mockSubscriptionService.verify((o) => o.getSubscriptions(mockAccount, mockCredentials), TypeMoq.Times.exactly(1));
|
||||||
mockCacheService.verify((o) => o.get(TypeMoq.It.isAnyString()), TypeMoq.Times.exactly(2));
|
mockCacheService.verify((o) => o.get(TypeMoq.It.isAnyString()), TypeMoq.Times.exactly(2));
|
||||||
mockCacheService.verify((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.exactly(1));
|
mockCacheService.verify((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.exactly(1));
|
||||||
@@ -267,7 +267,7 @@ describe('AzureResourceAccountTreeNode.getChildren', function(): void {
|
|||||||
|
|
||||||
const children = await accountTreeNode.getChildren();
|
const children = await accountTreeNode.getChildren();
|
||||||
|
|
||||||
mockCredentialService.verify((o) => o.getCredentials(mockAccount), TypeMoq.Times.once());
|
mockCredentialService.verify((o) => o.getCredentials(mockAccount, sqlops.AzureResource.ResourceManagement), TypeMoq.Times.once());
|
||||||
mockSubscriptionService.verify((o) => o.getSubscriptions(mockAccount, mockCredentials), TypeMoq.Times.once());
|
mockSubscriptionService.verify((o) => o.getSubscriptions(mockAccount, mockCredentials), TypeMoq.Times.once());
|
||||||
mockCacheService.verify((o) => o.get(TypeMoq.It.isAnyString()), TypeMoq.Times.never());
|
mockCacheService.verify((o) => o.get(TypeMoq.It.isAnyString()), TypeMoq.Times.never());
|
||||||
mockCacheService.verify((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.never());
|
mockCacheService.verify((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.never());
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ describe('AzureResourceDatabaseContainerTreeNode.getChildren', function(): void
|
|||||||
mockServicePool.credentialService = mockCredentialService.object;
|
mockServicePool.credentialService = mockCredentialService.object;
|
||||||
mockServicePool.databaseService = mockDatabaseService.object;
|
mockServicePool.databaseService = mockDatabaseService.object;
|
||||||
|
|
||||||
mockCredentialService.setup((o) => o.getCredentials(mockAccount)).returns(() => Promise.resolve(mockCredentials));
|
mockCredentialService.setup((o) => o.getCredentials(mockAccount, sqlops.AzureResource.ResourceManagement)).returns(() => Promise.resolve(mockCredentials));
|
||||||
mockCacheService.setup((o) => o.get(TypeMoq.It.isAnyString())).returns(() => mockDatabaseContainerCache);
|
mockCacheService.setup((o) => o.get(TypeMoq.It.isAnyString())).returns(() => mockDatabaseContainerCache);
|
||||||
mockCacheService.setup((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => mockDatabaseContainerCache.databases[mockSubscription.id] = mockDatabases);
|
mockCacheService.setup((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => mockDatabaseContainerCache.databases[mockSubscription.id] = mockDatabases);
|
||||||
});
|
});
|
||||||
@@ -130,7 +130,7 @@ describe('AzureResourceDatabaseContainerTreeNode.getChildren', function(): void
|
|||||||
|
|
||||||
const children = await databaseContainerTreeNode.getChildren();
|
const children = await databaseContainerTreeNode.getChildren();
|
||||||
|
|
||||||
mockCredentialService.verify((o) => o.getCredentials(mockAccount), TypeMoq.Times.once());
|
mockCredentialService.verify((o) => o.getCredentials(mockAccount, sqlops.AzureResource.ResourceManagement), TypeMoq.Times.once());
|
||||||
mockDatabaseService.verify((o) => o.getDatabases(mockSubscription, mockCredentials), TypeMoq.Times.once());
|
mockDatabaseService.verify((o) => o.getDatabases(mockSubscription, mockCredentials), TypeMoq.Times.once());
|
||||||
mockCacheService.verify((o) => o.get(TypeMoq.It.isAnyString()), TypeMoq.Times.once());
|
mockCacheService.verify((o) => o.get(TypeMoq.It.isAnyString()), TypeMoq.Times.once());
|
||||||
mockCacheService.verify((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.once());
|
mockCacheService.verify((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||||
@@ -160,7 +160,7 @@ describe('AzureResourceDatabaseContainerTreeNode.getChildren', function(): void
|
|||||||
await databaseContainerTreeNode.getChildren();
|
await databaseContainerTreeNode.getChildren();
|
||||||
const children = await databaseContainerTreeNode.getChildren();
|
const children = await databaseContainerTreeNode.getChildren();
|
||||||
|
|
||||||
mockCredentialService.verify((o) => o.getCredentials(mockAccount), TypeMoq.Times.exactly(1));
|
mockCredentialService.verify((o) => o.getCredentials(mockAccount, sqlops.AzureResource.ResourceManagement), TypeMoq.Times.exactly(1));
|
||||||
mockDatabaseService.verify((o) => o.getDatabases(mockSubscription, mockCredentials), TypeMoq.Times.exactly(1));
|
mockDatabaseService.verify((o) => o.getDatabases(mockSubscription, mockCredentials), TypeMoq.Times.exactly(1));
|
||||||
mockCacheService.verify((o) => o.get(TypeMoq.It.isAnyString()), TypeMoq.Times.exactly(2));
|
mockCacheService.verify((o) => o.get(TypeMoq.It.isAnyString()), TypeMoq.Times.exactly(2));
|
||||||
mockCacheService.verify((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.exactly(1));
|
mockCacheService.verify((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.exactly(1));
|
||||||
@@ -193,7 +193,7 @@ describe('AzureResourceDatabaseContainerTreeNode.getChildren', function(): void
|
|||||||
const databaseContainerTreeNode = new AzureResourceDatabaseContainerTreeNode(mockSubscription, mockAccount, mockTreeChangeHandler.object, undefined);
|
const databaseContainerTreeNode = new AzureResourceDatabaseContainerTreeNode(mockSubscription, mockAccount, mockTreeChangeHandler.object, undefined);
|
||||||
const children = await databaseContainerTreeNode.getChildren();
|
const children = await databaseContainerTreeNode.getChildren();
|
||||||
|
|
||||||
mockCredentialService.verify((o) => o.getCredentials(mockAccount), TypeMoq.Times.once());
|
mockCredentialService.verify((o) => o.getCredentials(mockAccount, sqlops.AzureResource.ResourceManagement), TypeMoq.Times.once());
|
||||||
mockDatabaseService.verify((o) => o.getDatabases(mockSubscription, mockCredentials), TypeMoq.Times.once());
|
mockDatabaseService.verify((o) => o.getDatabases(mockSubscription, mockCredentials), TypeMoq.Times.once());
|
||||||
mockCacheService.verify((o) => o.get(TypeMoq.It.isAnyString()), TypeMoq.Times.never());
|
mockCacheService.verify((o) => o.get(TypeMoq.It.isAnyString()), TypeMoq.Times.never());
|
||||||
mockCacheService.verify((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.never());
|
mockCacheService.verify((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.never());
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ describe('AzureResourceDatabaseServerContainerTreeNode.getChildren', function():
|
|||||||
mockServicePool.credentialService = mockCredentialService.object;
|
mockServicePool.credentialService = mockCredentialService.object;
|
||||||
mockServicePool.databaseServerService = mockDatabaseServerService.object;
|
mockServicePool.databaseServerService = mockDatabaseServerService.object;
|
||||||
|
|
||||||
mockCredentialService.setup((o) => o.getCredentials(mockAccount)).returns(() => Promise.resolve(mockCredentials));
|
mockCredentialService.setup((o) => o.getCredentials(mockAccount, sqlops.AzureResource.ResourceManagement)).returns(() => Promise.resolve(mockCredentials));
|
||||||
mockCacheService.setup((o) => o.get(TypeMoq.It.isAnyString())).returns(() => mockDatabaseServerContainerCache);
|
mockCacheService.setup((o) => o.get(TypeMoq.It.isAnyString())).returns(() => mockDatabaseServerContainerCache);
|
||||||
mockCacheService.setup((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => mockDatabaseServerContainerCache.databaseServers[mockSubscription.id] = mockDatabaseServers);
|
mockCacheService.setup((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => mockDatabaseServerContainerCache.databaseServers[mockSubscription.id] = mockDatabaseServers);
|
||||||
});
|
});
|
||||||
@@ -130,7 +130,7 @@ describe('AzureResourceDatabaseServerContainerTreeNode.getChildren', function():
|
|||||||
|
|
||||||
const children = await databaseServerContainerTreeNode.getChildren();
|
const children = await databaseServerContainerTreeNode.getChildren();
|
||||||
|
|
||||||
mockCredentialService.verify((o) => o.getCredentials(mockAccount), TypeMoq.Times.once());
|
mockCredentialService.verify((o) => o.getCredentials(mockAccount, sqlops.AzureResource.ResourceManagement), TypeMoq.Times.once());
|
||||||
mockDatabaseServerService.verify((o) => o.getDatabaseServers(mockSubscription, mockCredentials), TypeMoq.Times.once());
|
mockDatabaseServerService.verify((o) => o.getDatabaseServers(mockSubscription, mockCredentials), TypeMoq.Times.once());
|
||||||
mockCacheService.verify((o) => o.get(TypeMoq.It.isAnyString()), TypeMoq.Times.once());
|
mockCacheService.verify((o) => o.get(TypeMoq.It.isAnyString()), TypeMoq.Times.once());
|
||||||
mockCacheService.verify((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.once());
|
mockCacheService.verify((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.once());
|
||||||
@@ -160,7 +160,7 @@ describe('AzureResourceDatabaseServerContainerTreeNode.getChildren', function():
|
|||||||
await databaseServerContainerTreeNode.getChildren();
|
await databaseServerContainerTreeNode.getChildren();
|
||||||
const children = await databaseServerContainerTreeNode.getChildren();
|
const children = await databaseServerContainerTreeNode.getChildren();
|
||||||
|
|
||||||
mockCredentialService.verify((o) => o.getCredentials(mockAccount), TypeMoq.Times.exactly(1));
|
mockCredentialService.verify((o) => o.getCredentials(mockAccount, sqlops.AzureResource.ResourceManagement), TypeMoq.Times.exactly(1));
|
||||||
mockDatabaseServerService.verify((o) => o.getDatabaseServers(mockSubscription, mockCredentials), TypeMoq.Times.exactly(1));
|
mockDatabaseServerService.verify((o) => o.getDatabaseServers(mockSubscription, mockCredentials), TypeMoq.Times.exactly(1));
|
||||||
mockCacheService.verify((o) => o.get(TypeMoq.It.isAnyString()), TypeMoq.Times.exactly(2));
|
mockCacheService.verify((o) => o.get(TypeMoq.It.isAnyString()), TypeMoq.Times.exactly(2));
|
||||||
mockCacheService.verify((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.exactly(1));
|
mockCacheService.verify((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.exactly(1));
|
||||||
@@ -193,7 +193,7 @@ describe('AzureResourceDatabaseServerContainerTreeNode.getChildren', function():
|
|||||||
const databaseServerContainerTreeNode = new AzureResourceDatabaseServerContainerTreeNode(mockSubscription, mockAccount, mockTreeChangeHandler.object, undefined);
|
const databaseServerContainerTreeNode = new AzureResourceDatabaseServerContainerTreeNode(mockSubscription, mockAccount, mockTreeChangeHandler.object, undefined);
|
||||||
const children = await databaseServerContainerTreeNode.getChildren();
|
const children = await databaseServerContainerTreeNode.getChildren();
|
||||||
|
|
||||||
mockCredentialService.verify((o) => o.getCredentials(mockAccount), TypeMoq.Times.once());
|
mockCredentialService.verify((o) => o.getCredentials(mockAccount, sqlops.AzureResource.ResourceManagement), TypeMoq.Times.once());
|
||||||
mockDatabaseServerService.verify((o) => o.getDatabaseServers(mockSubscription, mockCredentials), TypeMoq.Times.once());
|
mockDatabaseServerService.verify((o) => o.getDatabaseServers(mockSubscription, mockCredentials), TypeMoq.Times.once());
|
||||||
mockCacheService.verify((o) => o.get(TypeMoq.It.isAnyString()), TypeMoq.Times.never());
|
mockCacheService.verify((o) => o.get(TypeMoq.It.isAnyString()), TypeMoq.Times.never());
|
||||||
mockCacheService.verify((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.never());
|
mockCacheService.verify((o) => o.update(TypeMoq.It.isAnyString(), TypeMoq.It.isAny()), TypeMoq.Times.never());
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
"@types/node@^8.0.24":
|
"@types/node@^8.0.24":
|
||||||
version "8.10.36"
|
version "8.10.36"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.36.tgz#eac05d576fbcd0b4ea3c912dc58c20475c08d9e4"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.36.tgz#eac05d576fbcd0b4ea3c912dc58c20475c08d9e4"
|
||||||
|
integrity sha512-SL6KhfM7PTqiFmbCW3eVNwVBZ+88Mrzbuvn9olPsfv43mbiWaFY+nRcz/TGGku0/lc2FepdMbImdMY1JrQ+zbw==
|
||||||
|
|
||||||
"@types/node@^8.0.47":
|
"@types/node@^8.0.47":
|
||||||
version "8.10.30"
|
version "8.10.30"
|
||||||
@@ -41,18 +42,6 @@ ajv@^5.3.0:
|
|||||||
fast-json-stable-stringify "^2.0.0"
|
fast-json-stable-stringify "^2.0.0"
|
||||||
json-schema-traverse "^0.3.0"
|
json-schema-traverse "^0.3.0"
|
||||||
|
|
||||||
ansi-regex@^2.0.0:
|
|
||||||
version "2.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
|
|
||||||
|
|
||||||
ansi-styles@^2.2.1:
|
|
||||||
version "2.2.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
|
|
||||||
|
|
||||||
asn1@0.1.11:
|
|
||||||
version "0.1.11"
|
|
||||||
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.1.11.tgz#559be18376d08a4ec4dbe80877d27818639b2df7"
|
|
||||||
|
|
||||||
asn1@~0.2.3:
|
asn1@~0.2.3:
|
||||||
version "0.2.4"
|
version "0.2.4"
|
||||||
resolved "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
|
resolved "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
|
||||||
@@ -65,10 +54,6 @@ assert-plus@1.0.0, assert-plus@^1.0.0:
|
|||||||
resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
|
resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
|
||||||
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
|
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
|
||||||
|
|
||||||
assert-plus@^0.1.5:
|
|
||||||
version "0.1.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.1.5.tgz#ee74009413002d84cec7219c6ac811812e723160"
|
|
||||||
|
|
||||||
async@2.6.0:
|
async@2.6.0:
|
||||||
version "2.6.0"
|
version "2.6.0"
|
||||||
resolved "https://registry.npmjs.org/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4"
|
resolved "https://registry.npmjs.org/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4"
|
||||||
@@ -76,9 +61,10 @@ async@2.6.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
lodash "^4.14.0"
|
lodash "^4.14.0"
|
||||||
|
|
||||||
async@>=0.6.0, async@^2.0.1:
|
async@>=0.6.0:
|
||||||
version "2.6.1"
|
version "2.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610"
|
resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610"
|
||||||
|
integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
lodash "^4.17.10"
|
lodash "^4.17.10"
|
||||||
|
|
||||||
@@ -87,10 +73,6 @@ asynckit@^0.4.0:
|
|||||||
resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||||
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
|
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
|
||||||
|
|
||||||
aws-sign2@~0.5.0:
|
|
||||||
version "0.5.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.5.0.tgz#c57103f7a17fc037f02d7c2e64b602ea223f7d63"
|
|
||||||
|
|
||||||
aws-sign2@~0.7.0:
|
aws-sign2@~0.7.0:
|
||||||
version "0.7.0"
|
version "0.7.0"
|
||||||
resolved "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
|
resolved "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
|
||||||
@@ -129,22 +111,6 @@ bcrypt-pbkdf@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
tweetnacl "^0.14.3"
|
tweetnacl "^0.14.3"
|
||||||
|
|
||||||
bl@~1.0.0:
|
|
||||||
version "1.0.3"
|
|
||||||
resolved "http://registry.npmjs.org/bl/-/bl-1.0.3.tgz#fc5421a28fd4226036c3b3891a66a25bc64d226e"
|
|
||||||
dependencies:
|
|
||||||
readable-stream "~2.0.5"
|
|
||||||
|
|
||||||
bluebird@^2.9.30:
|
|
||||||
version "2.11.0"
|
|
||||||
resolved "http://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
|
|
||||||
|
|
||||||
boom@2.x.x:
|
|
||||||
version "2.10.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f"
|
|
||||||
dependencies:
|
|
||||||
hoek "2.x.x"
|
|
||||||
|
|
||||||
brace-expansion@^1.1.7:
|
brace-expansion@^1.1.7:
|
||||||
version "1.1.11"
|
version "1.1.11"
|
||||||
resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||||
@@ -163,25 +129,11 @@ buffer-equal-constant-time@1.0.1:
|
|||||||
resolved "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
|
resolved "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
|
||||||
integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=
|
integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=
|
||||||
|
|
||||||
caseless@~0.11.0:
|
|
||||||
version "0.11.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7"
|
|
||||||
|
|
||||||
caseless@~0.12.0:
|
caseless@~0.12.0:
|
||||||
version "0.12.0"
|
version "0.12.0"
|
||||||
resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
|
resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
|
||||||
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
|
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
|
||||||
|
|
||||||
chalk@^1.0.0:
|
|
||||||
version "1.1.3"
|
|
||||||
resolved "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
|
|
||||||
dependencies:
|
|
||||||
ansi-styles "^2.2.1"
|
|
||||||
escape-string-regexp "^1.0.2"
|
|
||||||
has-ansi "^2.0.0"
|
|
||||||
strip-ansi "^3.0.0"
|
|
||||||
supports-color "^2.0.0"
|
|
||||||
|
|
||||||
circular-json@^0.3.1:
|
circular-json@^0.3.1:
|
||||||
version "0.3.3"
|
version "0.3.3"
|
||||||
resolved "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66"
|
resolved "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66"
|
||||||
@@ -199,9 +151,10 @@ combined-stream@1.0.6:
|
|||||||
dependencies:
|
dependencies:
|
||||||
delayed-stream "~1.0.0"
|
delayed-stream "~1.0.0"
|
||||||
|
|
||||||
combined-stream@^1.0.5, combined-stream@~1.0.1, combined-stream@~1.0.6:
|
combined-stream@~1.0.6:
|
||||||
version "1.0.7"
|
version "1.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828"
|
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828"
|
||||||
|
integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==
|
||||||
dependencies:
|
dependencies:
|
||||||
delayed-stream "~1.0.0"
|
delayed-stream "~1.0.0"
|
||||||
|
|
||||||
@@ -210,28 +163,15 @@ commander@2.15.1:
|
|||||||
resolved "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
|
resolved "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
|
||||||
integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==
|
integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==
|
||||||
|
|
||||||
commander@^2.8.1:
|
|
||||||
version "2.19.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
|
|
||||||
|
|
||||||
concat-map@0.0.1:
|
concat-map@0.0.1:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||||
|
|
||||||
core-util-is@1.0.2, core-util-is@~1.0.0:
|
core-util-is@1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||||
|
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||||
cryptiles@2.x.x:
|
|
||||||
version "2.0.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
|
|
||||||
dependencies:
|
|
||||||
boom "2.x.x"
|
|
||||||
|
|
||||||
ctype@0.5.3:
|
|
||||||
version "0.5.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/ctype/-/ctype-0.5.3.tgz#82c18c2461f74114ef16c135224ad0b9144ca12f"
|
|
||||||
|
|
||||||
dashdash@^1.12.0:
|
dashdash@^1.12.0:
|
||||||
version "1.14.1"
|
version "1.14.1"
|
||||||
@@ -282,13 +222,15 @@ ecdsa-sig-formatter@1.0.10:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer "^5.0.1"
|
safe-buffer "^5.0.1"
|
||||||
|
|
||||||
escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2:
|
escape-string-regexp@1.0.5:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||||
|
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
||||||
|
|
||||||
extend@~3.0.0, extend@~3.0.2:
|
extend@~3.0.2:
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
||||||
|
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
|
||||||
|
|
||||||
extsprintf@1.3.0:
|
extsprintf@1.3.0:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
@@ -310,17 +252,10 @@ fast-json-stable-stringify@^2.0.0:
|
|||||||
resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
|
resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
|
||||||
integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
|
integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
|
||||||
|
|
||||||
forever-agent@~0.6.0, forever-agent@~0.6.1:
|
forever-agent@~0.6.1:
|
||||||
version "0.6.1"
|
version "0.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
|
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
|
||||||
|
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
|
||||||
form-data@~1.0.0-rc1:
|
|
||||||
version "1.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-1.0.1.tgz#ae315db9a4907fa065502304a66d7733475ee37c"
|
|
||||||
dependencies:
|
|
||||||
async "^2.0.1"
|
|
||||||
combined-stream "^1.0.5"
|
|
||||||
mime-types "^2.1.11"
|
|
||||||
|
|
||||||
form-data@~2.3.2:
|
form-data@~2.3.2:
|
||||||
version "2.3.2"
|
version "2.3.2"
|
||||||
@@ -336,18 +271,6 @@ fs.realpath@^1.0.0:
|
|||||||
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||||
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
||||||
|
|
||||||
generate-function@^2.0.0:
|
|
||||||
version "2.3.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f"
|
|
||||||
dependencies:
|
|
||||||
is-property "^1.0.2"
|
|
||||||
|
|
||||||
generate-object-property@^1.1.0:
|
|
||||||
version "1.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0"
|
|
||||||
dependencies:
|
|
||||||
is-property "^1.0.0"
|
|
||||||
|
|
||||||
getpass@^0.1.1:
|
getpass@^0.1.1:
|
||||||
version "0.1.7"
|
version "0.1.7"
|
||||||
resolved "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
|
resolved "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
|
||||||
@@ -377,15 +300,6 @@ har-schema@^2.0.0:
|
|||||||
resolved "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
|
resolved "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
|
||||||
integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
|
integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
|
||||||
|
|
||||||
har-validator@^1.6.1:
|
|
||||||
version "1.8.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-1.8.0.tgz#d83842b0eb4c435960aeb108a067a3aa94c0eeb2"
|
|
||||||
dependencies:
|
|
||||||
bluebird "^2.9.30"
|
|
||||||
chalk "^1.0.0"
|
|
||||||
commander "^2.8.1"
|
|
||||||
is-my-json-valid "^2.12.0"
|
|
||||||
|
|
||||||
har-validator@~5.1.0:
|
har-validator@~5.1.0:
|
||||||
version "5.1.0"
|
version "5.1.0"
|
||||||
resolved "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29"
|
resolved "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29"
|
||||||
@@ -394,43 +308,16 @@ har-validator@~5.1.0:
|
|||||||
ajv "^5.3.0"
|
ajv "^5.3.0"
|
||||||
har-schema "^2.0.0"
|
har-schema "^2.0.0"
|
||||||
|
|
||||||
has-ansi@^2.0.0:
|
|
||||||
version "2.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
|
|
||||||
dependencies:
|
|
||||||
ansi-regex "^2.0.0"
|
|
||||||
|
|
||||||
has-flag@^3.0.0:
|
has-flag@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
||||||
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
|
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
|
||||||
|
|
||||||
hawk@~3.1.0:
|
|
||||||
version "3.1.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
|
|
||||||
dependencies:
|
|
||||||
boom "2.x.x"
|
|
||||||
cryptiles "2.x.x"
|
|
||||||
hoek "2.x.x"
|
|
||||||
sntp "1.x.x"
|
|
||||||
|
|
||||||
he@1.1.1:
|
he@1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.npmjs.org/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
|
resolved "https://registry.npmjs.org/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
|
||||||
integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0=
|
integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0=
|
||||||
|
|
||||||
hoek@2.x.x:
|
|
||||||
version "2.16.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
|
|
||||||
|
|
||||||
http-signature@~0.11.0:
|
|
||||||
version "0.11.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-0.11.0.tgz#1796cf67a001ad5cd6849dca0991485f09089fe6"
|
|
||||||
dependencies:
|
|
||||||
asn1 "0.1.11"
|
|
||||||
assert-plus "^0.1.5"
|
|
||||||
ctype "0.5.3"
|
|
||||||
|
|
||||||
http-signature@~1.2.0:
|
http-signature@~1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
|
resolved "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
|
||||||
@@ -448,33 +335,16 @@ inflight@^1.0.4:
|
|||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
inherits@2, inherits@~2.0.1:
|
inherits@2:
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||||
|
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
|
||||||
|
|
||||||
is-buffer@^1.1.6:
|
is-buffer@^1.1.6:
|
||||||
version "1.1.6"
|
version "1.1.6"
|
||||||
resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
||||||
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
|
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
|
||||||
|
|
||||||
is-my-ip-valid@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824"
|
|
||||||
|
|
||||||
is-my-json-valid@^2.12.0:
|
|
||||||
version "2.19.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz#8fd6e40363cd06b963fa877d444bfb5eddc62175"
|
|
||||||
dependencies:
|
|
||||||
generate-function "^2.0.0"
|
|
||||||
generate-object-property "^1.1.0"
|
|
||||||
is-my-ip-valid "^1.0.0"
|
|
||||||
jsonpointer "^4.0.0"
|
|
||||||
xtend "^4.0.0"
|
|
||||||
|
|
||||||
is-property@^1.0.0, is-property@^1.0.2:
|
|
||||||
version "1.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
|
|
||||||
|
|
||||||
is-stream@^1.1.0:
|
is-stream@^1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
|
resolved "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
|
||||||
@@ -485,13 +355,10 @@ is-typedarray@~1.0.0:
|
|||||||
resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
|
resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
|
||||||
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
|
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
|
||||||
|
|
||||||
isarray@~1.0.0:
|
isstream@~0.1.2:
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
|
||||||
|
|
||||||
isstream@~0.1.1, isstream@~0.1.2:
|
|
||||||
version "0.1.2"
|
version "0.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
|
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
|
||||||
|
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
|
||||||
|
|
||||||
jsbn@~0.1.0:
|
jsbn@~0.1.0:
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
@@ -508,13 +375,10 @@ json-schema@0.2.3:
|
|||||||
resolved "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
|
resolved "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
|
||||||
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
|
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
|
||||||
|
|
||||||
json-stringify-safe@~5.0.0, json-stringify-safe@~5.0.1:
|
json-stringify-safe@~5.0.1:
|
||||||
version "5.0.1"
|
version "5.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
||||||
|
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
|
||||||
jsonpointer@^4.0.0:
|
|
||||||
version "4.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9"
|
|
||||||
|
|
||||||
jsprim@^1.2.2:
|
jsprim@^1.2.2:
|
||||||
version "1.4.1"
|
version "1.4.1"
|
||||||
@@ -553,9 +417,10 @@ mime-db@~1.36.0:
|
|||||||
resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397"
|
resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397"
|
||||||
integrity sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==
|
integrity sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==
|
||||||
|
|
||||||
mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.2:
|
mime-types@^2.1.12, mime-types@~2.1.19:
|
||||||
version "2.1.20"
|
version "2.1.20"
|
||||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19"
|
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19"
|
||||||
|
integrity sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==
|
||||||
dependencies:
|
dependencies:
|
||||||
mime-db "~1.36.0"
|
mime-db "~1.36.0"
|
||||||
|
|
||||||
@@ -631,14 +496,6 @@ ms@2.0.0:
|
|||||||
resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||||
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
|
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
|
||||||
|
|
||||||
node-uuid@~1.4.0:
|
|
||||||
version "1.4.8"
|
|
||||||
resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907"
|
|
||||||
|
|
||||||
oauth-sign@~0.8.0:
|
|
||||||
version "0.8.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
|
|
||||||
|
|
||||||
oauth-sign@~0.9.0:
|
oauth-sign@~0.9.0:
|
||||||
version "0.9.0"
|
version "0.9.0"
|
||||||
resolved "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
resolved "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||||
@@ -666,10 +523,6 @@ postinstall-build@^5.0.1:
|
|||||||
resolved "https://registry.npmjs.org/postinstall-build/-/postinstall-build-5.0.3.tgz#238692f712a481d8f5bc8960e94786036241efc7"
|
resolved "https://registry.npmjs.org/postinstall-build/-/postinstall-build-5.0.3.tgz#238692f712a481d8f5bc8960e94786036241efc7"
|
||||||
integrity sha512-vPvPe8TKgp4FLgY3+DfxCE5PIfoXBK2lyLfNCxsRbDsV6vS4oU5RG/IWxrblMn6heagbnMED3MemUQllQ2bQUg==
|
integrity sha512-vPvPe8TKgp4FLgY3+DfxCE5PIfoXBK2lyLfNCxsRbDsV6vS4oU5RG/IWxrblMn6heagbnMED3MemUQllQ2bQUg==
|
||||||
|
|
||||||
process-nextick-args@~1.0.6:
|
|
||||||
version "1.0.7"
|
|
||||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
|
|
||||||
|
|
||||||
psl@^1.1.24:
|
psl@^1.1.24:
|
||||||
version "1.1.29"
|
version "1.1.29"
|
||||||
resolved "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67"
|
resolved "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67"
|
||||||
@@ -680,53 +533,14 @@ punycode@^1.4.1:
|
|||||||
resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
|
resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
|
||||||
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
|
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
|
||||||
|
|
||||||
qs@~5.1.0:
|
|
||||||
version "5.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/qs/-/qs-5.1.0.tgz#4d932e5c7ea411cca76a312d39a606200fd50cd9"
|
|
||||||
|
|
||||||
qs@~6.5.2:
|
qs@~6.5.2:
|
||||||
version "6.5.2"
|
version "6.5.2"
|
||||||
resolved "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
|
resolved "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
|
||||||
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
|
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
|
||||||
|
|
||||||
readable-stream@~2.0.5:
|
request@2.88.0, "request@>= 2.52.0", request@^2.88.0:
|
||||||
version "2.0.6"
|
|
||||||
resolved "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e"
|
|
||||||
dependencies:
|
|
||||||
core-util-is "~1.0.0"
|
|
||||||
inherits "~2.0.1"
|
|
||||||
isarray "~1.0.0"
|
|
||||||
process-nextick-args "~1.0.6"
|
|
||||||
string_decoder "~0.10.x"
|
|
||||||
util-deprecate "~1.0.1"
|
|
||||||
|
|
||||||
request@2.63.0:
|
|
||||||
version "2.63.0"
|
|
||||||
resolved "http://registry.npmjs.org/request/-/request-2.63.0.tgz#c83e7c3485e5d9bf9b146318429bc48f1253d8be"
|
|
||||||
dependencies:
|
|
||||||
aws-sign2 "~0.5.0"
|
|
||||||
bl "~1.0.0"
|
|
||||||
caseless "~0.11.0"
|
|
||||||
combined-stream "~1.0.1"
|
|
||||||
extend "~3.0.0"
|
|
||||||
forever-agent "~0.6.0"
|
|
||||||
form-data "~1.0.0-rc1"
|
|
||||||
har-validator "^1.6.1"
|
|
||||||
hawk "~3.1.0"
|
|
||||||
http-signature "~0.11.0"
|
|
||||||
isstream "~0.1.1"
|
|
||||||
json-stringify-safe "~5.0.0"
|
|
||||||
mime-types "~2.1.2"
|
|
||||||
node-uuid "~1.4.0"
|
|
||||||
oauth-sign "~0.8.0"
|
|
||||||
qs "~5.1.0"
|
|
||||||
stringstream "~0.0.4"
|
|
||||||
tough-cookie ">=0.12.0"
|
|
||||||
tunnel-agent "~0.4.0"
|
|
||||||
|
|
||||||
"request@>= 2.52.0", request@^2.88.0:
|
|
||||||
version "2.88.0"
|
version "2.88.0"
|
||||||
resolved "https://registry.npmjs.org/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
|
resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
|
||||||
integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==
|
integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==
|
||||||
dependencies:
|
dependencies:
|
||||||
aws-sign2 "~0.7.0"
|
aws-sign2 "~0.7.0"
|
||||||
@@ -804,12 +618,6 @@ should@^13.2.1:
|
|||||||
should-type-adaptors "^1.0.1"
|
should-type-adaptors "^1.0.1"
|
||||||
should-util "^1.0.0"
|
should-util "^1.0.0"
|
||||||
|
|
||||||
sntp@1.x.x:
|
|
||||||
version "1.0.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198"
|
|
||||||
dependencies:
|
|
||||||
hoek "2.x.x"
|
|
||||||
|
|
||||||
sshpk@^1.7.0:
|
sshpk@^1.7.0:
|
||||||
version "1.14.2"
|
version "1.14.2"
|
||||||
resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98"
|
resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98"
|
||||||
@@ -826,20 +634,6 @@ sshpk@^1.7.0:
|
|||||||
jsbn "~0.1.0"
|
jsbn "~0.1.0"
|
||||||
tweetnacl "~0.14.0"
|
tweetnacl "~0.14.0"
|
||||||
|
|
||||||
string_decoder@~0.10.x:
|
|
||||||
version "0.10.31"
|
|
||||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
|
|
||||||
|
|
||||||
stringstream@~0.0.4:
|
|
||||||
version "0.0.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72"
|
|
||||||
|
|
||||||
strip-ansi@^3.0.0:
|
|
||||||
version "3.0.1"
|
|
||||||
resolved "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
|
|
||||||
dependencies:
|
|
||||||
ansi-regex "^2.0.0"
|
|
||||||
|
|
||||||
supports-color@5.4.0:
|
supports-color@5.4.0:
|
||||||
version "5.4.0"
|
version "5.4.0"
|
||||||
resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54"
|
resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54"
|
||||||
@@ -847,18 +641,15 @@ supports-color@5.4.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
has-flag "^3.0.0"
|
has-flag "^3.0.0"
|
||||||
|
|
||||||
supports-color@^2.0.0:
|
|
||||||
version "2.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
|
|
||||||
|
|
||||||
through@^2.3.8:
|
through@^2.3.8:
|
||||||
version "2.3.8"
|
version "2.3.8"
|
||||||
resolved "http://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
resolved "http://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||||
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
|
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
|
||||||
|
|
||||||
tough-cookie@>=0.12.0, tough-cookie@~2.4.3:
|
tough-cookie@~2.4.3:
|
||||||
version "2.4.3"
|
version "2.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
|
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
|
||||||
|
integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
psl "^1.1.24"
|
psl "^1.1.24"
|
||||||
punycode "^1.4.1"
|
punycode "^1.4.1"
|
||||||
@@ -870,10 +661,6 @@ tunnel-agent@^0.6.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer "^5.0.1"
|
safe-buffer "^5.0.1"
|
||||||
|
|
||||||
tunnel-agent@~0.4.0:
|
|
||||||
version "0.4.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb"
|
|
||||||
|
|
||||||
tunnel@0.0.5:
|
tunnel@0.0.5:
|
||||||
version "0.0.5"
|
version "0.0.5"
|
||||||
resolved "https://registry.npmjs.org/tunnel/-/tunnel-0.0.5.tgz#d1532254749ed36620fcd1010865495a1fa9d0ae"
|
resolved "https://registry.npmjs.org/tunnel/-/tunnel-0.0.5.tgz#d1532254749ed36620fcd1010865495a1fa9d0ae"
|
||||||
@@ -898,10 +685,6 @@ typemoq@^2.1.0:
|
|||||||
resolved "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961"
|
resolved "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961"
|
||||||
integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==
|
integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==
|
||||||
|
|
||||||
util-deprecate@~1.0.1:
|
|
||||||
version "1.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
|
||||||
|
|
||||||
uuid@^3.1.0, uuid@^3.2.1, uuid@^3.3.2:
|
uuid@^3.1.0, uuid@^3.2.1, uuid@^3.3.2:
|
||||||
version "3.3.2"
|
version "3.3.2"
|
||||||
resolved "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
|
resolved "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
|
||||||
@@ -934,7 +717,3 @@ wrappy@1:
|
|||||||
xpath.js@~1.1.0:
|
xpath.js@~1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.npmjs.org/xpath.js/-/xpath.js-1.1.0.tgz#3816a44ed4bb352091083d002a383dd5104a5ff1"
|
resolved "https://registry.npmjs.org/xpath.js/-/xpath.js-1.1.0.tgz#3816a44ed4bb352091083d002a383dd5104a5ff1"
|
||||||
|
|
||||||
xtend@^4.0.0:
|
|
||||||
version "4.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
|
|
||||||
|
|||||||
@@ -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.4.0",
|
"version": "0.5.0",
|
||||||
"publisher": "Microsoft",
|
"publisher": "Microsoft",
|
||||||
"preview": true,
|
"preview": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -33,6 +33,15 @@
|
|||||||
"light": "./images/light_icon.svg",
|
"light": "./images/light_icon.svg",
|
||||||
"dark": "./images/dark_icon.svg"
|
"dark": "./images/dark_icon.svg"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "dacFx.start",
|
||||||
|
"title": "Data-tier Application Wizard",
|
||||||
|
"category": "Data-tier Application",
|
||||||
|
"icon": {
|
||||||
|
"light": "./images/light_icon.svg",
|
||||||
|
"dark": "./images/dark_icon.svg"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"keybindings": [
|
"keybindings": [
|
||||||
@@ -48,12 +57,17 @@
|
|||||||
"command": "flatFileImport.start",
|
"command": "flatFileImport.start",
|
||||||
"when": "connectionProvider == MSSQL && nodeType && nodeType == Database",
|
"when": "connectionProvider == MSSQL && nodeType && nodeType == Database",
|
||||||
"group": "import"
|
"group": "import"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "dacFx.start",
|
||||||
|
"when": "connectionProvider == MSSQL && nodeType && nodeType == Database",
|
||||||
|
"group": "export"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.2.7",
|
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.2.10",
|
||||||
"opener": "^1.4.3",
|
"opener": "^1.4.3",
|
||||||
"service-downloader": "github:anthonydresser/service-downloader#0.1.5",
|
"service-downloader": "github:anthonydresser/service-downloader#0.1.5",
|
||||||
"vscode-extension-telemetry": "0.0.18",
|
"vscode-extension-telemetry": "0.0.18",
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { FlatFileWizard } from '../wizard/flatFileWizard';
|
|||||||
import { ServiceClient } from '../services/serviceClient';
|
import { ServiceClient } from '../services/serviceClient';
|
||||||
import { ApiType, managerInstance } from '../services/serviceApiManager';
|
import { ApiType, managerInstance } from '../services/serviceApiManager';
|
||||||
import { FlatFileProvider } from '../services/contracts';
|
import { FlatFileProvider } from '../services/contracts';
|
||||||
|
import { DataTierApplicationWizard } from '../wizard/dataTierApplicationWizard';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main controller class that initializes the extension
|
* The main controller class that initializes the extension
|
||||||
@@ -35,10 +36,15 @@ export default class MainController extends ControllerBase {
|
|||||||
this.initializeFlatFileProvider(provider);
|
this.initializeFlatFileProvider(provider);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.initializeDacFxWizard();
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeFlatFileProvider(provider: FlatFileProvider) {
|
private initializeFlatFileProvider(provider: FlatFileProvider) {
|
||||||
sqlops.tasks.registerTask('flatFileImport.start', (profile: sqlops.IConnectionProfile, ...args: any[]) => new FlatFileWizard(provider).start(profile, args));
|
sqlops.tasks.registerTask('flatFileImport.start', (profile: sqlops.IConnectionProfile, ...args: any[]) => new FlatFileWizard(provider).start(profile, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private initializeDacFxWizard() {
|
||||||
|
sqlops.tasks.registerTask('dacFx.start', (profile: sqlops.IConnectionProfile, ...args: any[]) => new DataTierApplicationWizard().start(profile, args));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
139
extensions/import/src/wizard/api/basePage.ts
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 * as sqlops from 'sqlops';
|
||||||
|
import { BaseDataModel } from './models';
|
||||||
|
|
||||||
|
export abstract class BasePage {
|
||||||
|
|
||||||
|
protected readonly wizardPage: sqlops.window.modelviewdialog.WizardPage;
|
||||||
|
protected readonly model: BaseDataModel;
|
||||||
|
protected readonly view: sqlops.ModelView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method constructs all the elements of the page.
|
||||||
|
* @returns {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
public async abstract start(): Promise<boolean>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called when the user is entering the page.
|
||||||
|
* @returns {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
public async abstract onPageEnter(): Promise<boolean>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called when the user is leaving the page.
|
||||||
|
* @returns {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
async onPageLeave(): Promise<boolean> {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override this method to cleanup what you don't need cached in the page.
|
||||||
|
* @returns {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
public async cleanup(): Promise<boolean> {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up a navigation validator.
|
||||||
|
* This will be called right before onPageEnter().
|
||||||
|
*/
|
||||||
|
public abstract setupNavigationValidator();
|
||||||
|
|
||||||
|
protected async getServerValues(): Promise<{ connection, displayName, name }[]> {
|
||||||
|
let cons = await sqlops.connection.getActiveConnections();
|
||||||
|
// This user has no active connections ABORT MISSION
|
||||||
|
if (!cons || cons.length === 0) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
let count = -1;
|
||||||
|
let idx = -1;
|
||||||
|
|
||||||
|
|
||||||
|
let values = cons.map(c => {
|
||||||
|
// Handle the code to remember what the user's choice was from before
|
||||||
|
count++;
|
||||||
|
if (idx === -1) {
|
||||||
|
if (this.model.server && c.connectionId === this.model.server.connectionId) {
|
||||||
|
idx = count;
|
||||||
|
} else if (this.model.serverId && c.connectionId === this.model.serverId) {
|
||||||
|
idx = count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let db = c.options.databaseDisplayName;
|
||||||
|
let usr = c.options.user;
|
||||||
|
let srv = c.options.server;
|
||||||
|
|
||||||
|
if (!db) {
|
||||||
|
db = '<default>';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!usr) {
|
||||||
|
usr = 'default';
|
||||||
|
}
|
||||||
|
|
||||||
|
let finalName = `${srv}, ${db} (${usr})`;
|
||||||
|
return {
|
||||||
|
connection: c,
|
||||||
|
displayName: finalName,
|
||||||
|
name: c.connectionId
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
if (idx >= 0) {
|
||||||
|
let tmp = values[0];
|
||||||
|
values[0] = values[idx];
|
||||||
|
values[idx] = tmp;
|
||||||
|
} else {
|
||||||
|
this.deleteServerValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async getDatabaseValues(): Promise<{ displayName, name }[]> {
|
||||||
|
let idx = -1;
|
||||||
|
let count = -1;
|
||||||
|
let values = (await sqlops.connection.listDatabases(this.model.server.connectionId)).map(db => {
|
||||||
|
count++;
|
||||||
|
if (this.model.database && db === this.model.database) {
|
||||||
|
idx = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
displayName: db,
|
||||||
|
name: db
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
if (idx >= 0) {
|
||||||
|
let tmp = values[0];
|
||||||
|
values[0] = values[idx];
|
||||||
|
values[idx] = tmp;
|
||||||
|
} else {
|
||||||
|
this.deleteDatabaseValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected deleteServerValues() {
|
||||||
|
delete this.model.server;
|
||||||
|
delete this.model.serverId;
|
||||||
|
delete this.model.database;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected deleteDatabaseValues() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
158
extensions/import/src/wizard/api/dacFxConfigPage.ts
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 * as sqlops from 'sqlops';
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
|
import * as os from 'os';
|
||||||
|
import * as path from 'path';
|
||||||
|
import { DataTierApplicationWizard } from '../dataTierApplicationWizard';
|
||||||
|
import { DacFxDataModel } from './models';
|
||||||
|
import { BasePage } from './basePage';
|
||||||
|
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
|
export abstract class DacFxConfigPage extends BasePage {
|
||||||
|
|
||||||
|
protected readonly wizardPage: sqlops.window.modelviewdialog.WizardPage;
|
||||||
|
protected readonly instance: DataTierApplicationWizard;
|
||||||
|
protected readonly model: DacFxDataModel;
|
||||||
|
protected readonly view: sqlops.ModelView;
|
||||||
|
protected serverDropdown: sqlops.DropDownComponent;
|
||||||
|
protected databaseTextBox: sqlops.InputBoxComponent;
|
||||||
|
protected databaseDropdown: sqlops.DropDownComponent;
|
||||||
|
protected databaseLoader: sqlops.LoadingComponent;
|
||||||
|
protected fileTextBox: sqlops.InputBoxComponent;
|
||||||
|
protected fileButton: sqlops.ButtonComponent;
|
||||||
|
protected fileExtension: string;
|
||||||
|
|
||||||
|
protected constructor(instance: DataTierApplicationWizard, wizardPage: sqlops.window.modelviewdialog.WizardPage, model: DacFxDataModel, view: sqlops.ModelView) {
|
||||||
|
super();
|
||||||
|
this.instance = instance;
|
||||||
|
this.wizardPage = wizardPage;
|
||||||
|
this.model = model;
|
||||||
|
this.view = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setupNavigationValidator() {
|
||||||
|
this.instance.registerNavigationValidator(() => {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async createServerDropdown(isTargetServer: boolean): Promise<sqlops.FormComponent> {
|
||||||
|
this.serverDropdown = this.view.modelBuilder.dropDown().withProperties({
|
||||||
|
required: true
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
// Handle server changes
|
||||||
|
this.serverDropdown.onValueChanged(async () => {
|
||||||
|
this.model.server = (this.serverDropdown.value as ConnectionDropdownValue).connection;
|
||||||
|
this.model.serverName = (this.serverDropdown.value as ConnectionDropdownValue).displayName;
|
||||||
|
await this.populateDatabaseDropdown();
|
||||||
|
});
|
||||||
|
|
||||||
|
let targetServerTitle = localize('dacFx.targetServerDropdownTitle', 'Target Server');
|
||||||
|
let sourceServerTitle = localize('dacFx.sourceServerDropdownTitle', 'Source Server');
|
||||||
|
|
||||||
|
return {
|
||||||
|
component: this.serverDropdown,
|
||||||
|
title: isTargetServer ? targetServerTitle : sourceServerTitle
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async populateServerDropdown(): Promise<boolean> {
|
||||||
|
let values = await this.getServerValues();
|
||||||
|
if (values === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.model.server = values[0].connection;
|
||||||
|
this.model.serverName = values[0].displayName;
|
||||||
|
|
||||||
|
this.serverDropdown.updateProperties({
|
||||||
|
values: values
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async createDatabaseTextBox(): Promise<sqlops.FormComponent> {
|
||||||
|
this.databaseTextBox = this.view.modelBuilder.inputBox().withProperties({
|
||||||
|
required: true
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this.databaseTextBox.onTextChanged(async () => {
|
||||||
|
this.model.database = this.databaseTextBox.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
component: this.databaseTextBox,
|
||||||
|
title: localize('dacFx.databaseNameTextBox', 'Target Database')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async createDatabaseDropdown(): Promise<sqlops.FormComponent> {
|
||||||
|
this.databaseDropdown = this.view.modelBuilder.dropDown().withProperties({
|
||||||
|
required: true
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
// Handle database changes
|
||||||
|
this.databaseDropdown.onValueChanged(async () => {
|
||||||
|
this.model.database = (<sqlops.CategoryValue>this.databaseDropdown.value).name;
|
||||||
|
this.fileTextBox.value = this.generateFilePath();
|
||||||
|
this.model.filePath = this.fileTextBox.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.databaseLoader = this.view.modelBuilder.loadingComponent().withItem(this.databaseDropdown).component();
|
||||||
|
|
||||||
|
return {
|
||||||
|
component: this.databaseLoader,
|
||||||
|
title: localize('dacFx.sourceDatabaseDropdownTitle', 'Source Database')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async populateDatabaseDropdown(): Promise<boolean> {
|
||||||
|
this.databaseLoader.loading = true;
|
||||||
|
this.databaseDropdown.updateProperties({ values: [] });
|
||||||
|
|
||||||
|
if (!this.model.server) {
|
||||||
|
this.databaseLoader.loading = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let values = await this.getDatabaseValues();
|
||||||
|
this.model.database = values[0].name;
|
||||||
|
this.model.filePath = this.generateFilePath();
|
||||||
|
this.fileTextBox.value = this.model.filePath;
|
||||||
|
|
||||||
|
this.databaseDropdown.updateProperties({
|
||||||
|
values: values
|
||||||
|
});
|
||||||
|
this.databaseLoader.loading = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async createFileBrowserParts() {
|
||||||
|
this.fileTextBox = this.view.modelBuilder.inputBox().withProperties({
|
||||||
|
required: true
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this.fileButton = this.view.modelBuilder.button().withProperties({
|
||||||
|
label: '•••',
|
||||||
|
}).component();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected generateFilePath(): string {
|
||||||
|
let now = new Date();
|
||||||
|
let datetime = now.getFullYear() + '-' + (now.getMonth() + 1) + '-' + now.getDate() + '-' + now.getHours() + '-' + now.getMinutes();
|
||||||
|
return path.join(os.homedir(), this.model.database + '-' + datetime + this.fileExtension);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ConnectionDropdownValue extends sqlops.CategoryValue {
|
||||||
|
connection: sqlops.connection.Connection;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -8,8 +8,9 @@ import { ImportDataModel } from './models';
|
|||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
import { FlatFileProvider } from '../../services/contracts';
|
import { FlatFileProvider } from '../../services/contracts';
|
||||||
import { FlatFileWizard } from '../flatFileWizard';
|
import { FlatFileWizard } from '../flatFileWizard';
|
||||||
|
import { BasePage } from './basePage';
|
||||||
|
|
||||||
export abstract class ImportPage {
|
export abstract class ImportPage extends BasePage {
|
||||||
|
|
||||||
protected readonly wizardPage: sqlops.window.modelviewdialog.WizardPage;
|
protected readonly wizardPage: sqlops.window.modelviewdialog.WizardPage;
|
||||||
protected readonly instance: FlatFileWizard;
|
protected readonly instance: FlatFileWizard;
|
||||||
@@ -18,42 +19,11 @@ export abstract class ImportPage {
|
|||||||
protected readonly provider: FlatFileProvider;
|
protected readonly provider: FlatFileProvider;
|
||||||
|
|
||||||
protected constructor(instance: FlatFileWizard, wizardPage: sqlops.window.modelviewdialog.WizardPage, model: ImportDataModel, view: sqlops.ModelView, provider: FlatFileProvider) {
|
protected constructor(instance: FlatFileWizard, wizardPage: sqlops.window.modelviewdialog.WizardPage, model: ImportDataModel, view: sqlops.ModelView, provider: FlatFileProvider) {
|
||||||
|
super();
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
this.wizardPage = wizardPage;
|
this.wizardPage = wizardPage;
|
||||||
this.model = model;
|
this.model = model;
|
||||||
this.view = view;
|
this.view = view;
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method constructs all the elements of the page.
|
|
||||||
* @returns {Promise<boolean>}
|
|
||||||
*/
|
|
||||||
public async abstract start(): Promise<boolean>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called when the user is entering the page.
|
|
||||||
* @returns {Promise<boolean>}
|
|
||||||
*/
|
|
||||||
public async abstract onPageEnter(): Promise<boolean>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called when the user is leaving the page.
|
|
||||||
* @returns {Promise<boolean>}
|
|
||||||
*/
|
|
||||||
public async abstract onPageLeave(): Promise<boolean>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up a navigation validator.
|
|
||||||
* This will be called right before onPageEnter().
|
|
||||||
*/
|
|
||||||
public abstract setupNavigationValidator();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Override this method to cleanup what you don't need cached in the page.
|
|
||||||
* @returns {Promise<boolean>}
|
|
||||||
*/
|
|
||||||
public async cleanup(): Promise<boolean> {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,15 +6,19 @@
|
|||||||
|
|
||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
|
|
||||||
|
export interface BaseDataModel {
|
||||||
|
server: sqlops.connection.Connection;
|
||||||
|
serverId: string;
|
||||||
|
database: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main data model that communicates between the pages.
|
* The main data model that communicates between the pages.
|
||||||
*/
|
*/
|
||||||
export interface ImportDataModel {
|
export interface ImportDataModel extends BaseDataModel {
|
||||||
ownerUri: string;
|
ownerUri: string;
|
||||||
proseColumns: ColumnMetadata[];
|
proseColumns: ColumnMetadata[];
|
||||||
proseDataPreview: string[][];
|
proseDataPreview: string[][];
|
||||||
server: sqlops.connection.Connection;
|
|
||||||
serverId: string;
|
|
||||||
database: string;
|
database: string;
|
||||||
table: string;
|
table: string;
|
||||||
schema: string;
|
schema: string;
|
||||||
@@ -31,3 +35,14 @@ export interface ColumnMetadata {
|
|||||||
primaryKey: boolean;
|
primaryKey: boolean;
|
||||||
nullable: boolean;
|
nullable: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data model to communicate between DacFx pages
|
||||||
|
*/
|
||||||
|
export interface DacFxDataModel extends BaseDataModel {
|
||||||
|
serverName: string;
|
||||||
|
serverId: string;
|
||||||
|
filePath: string;
|
||||||
|
version: string;
|
||||||
|
upgradeExisting: boolean;
|
||||||
|
}
|
||||||
|
|||||||
253
extensions/import/src/wizard/dataTierApplicationWizard.ts
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 * as vscode from 'vscode';
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
|
import * as sqlops from 'sqlops';
|
||||||
|
import { SelectOperationPage } from './pages/selectOperationpage';
|
||||||
|
import { DeployConfigPage } from './pages/deployConfigPage';
|
||||||
|
import { DacFxSummaryPage } from './pages/dacFxSummaryPage';
|
||||||
|
import { ExportConfigPage } from './pages/exportConfigPage';
|
||||||
|
import { ExtractConfigPage } from './pages/extractConfigPage';
|
||||||
|
import { ImportConfigPage } from './pages/importConfigPage';
|
||||||
|
import { DacFxDataModel } from './api/models';
|
||||||
|
import { BasePage } from './api/basePage';
|
||||||
|
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
|
class Page {
|
||||||
|
wizardPage: sqlops.window.modelviewdialog.WizardPage;
|
||||||
|
dacFxPage: BasePage;
|
||||||
|
|
||||||
|
constructor(wizardPage: sqlops.window.modelviewdialog.WizardPage) {
|
||||||
|
this.wizardPage = wizardPage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Operation {
|
||||||
|
deploy,
|
||||||
|
extract,
|
||||||
|
import,
|
||||||
|
export
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DataTierApplicationWizard {
|
||||||
|
public wizard: sqlops.window.modelviewdialog.Wizard;
|
||||||
|
private connection: sqlops.connection.Connection;
|
||||||
|
private model: DacFxDataModel;
|
||||||
|
public pages: Map<string, Page> = new Map<string, Page>();
|
||||||
|
public selectedOperation: Operation;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public async start(p: any, ...args: any[]) {
|
||||||
|
this.model = <DacFxDataModel>{};
|
||||||
|
|
||||||
|
let profile = p ? <sqlops.IConnectionProfile>p.connectionProfile : undefined;
|
||||||
|
if (profile) {
|
||||||
|
this.model.serverId = profile.id;
|
||||||
|
this.model.database = profile.databaseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.connection = await sqlops.connection.getCurrentConnection();
|
||||||
|
if (!this.connection) {
|
||||||
|
this.connection = await sqlops.connection.openConnectionDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.wizard = sqlops.window.modelviewdialog.createWizard('Data-tier Application Wizard');
|
||||||
|
let selectOperationWizardPage = sqlops.window.modelviewdialog.createWizardPage(localize('dacFx.selectOperationPageName', 'Select an Operation'));
|
||||||
|
let deployConfigWizardPage = sqlops.window.modelviewdialog.createWizardPage(localize('dacFx.deployConfigPageName', 'Select Deploy Dacpac Settings'));
|
||||||
|
let summaryWizardPage = sqlops.window.modelviewdialog.createWizardPage(localize('dacFx.summaryPageName', 'Summary'));
|
||||||
|
let extractConfigWizardPage = sqlops.window.modelviewdialog.createWizardPage(localize('dacFx.extractConfigPageName', 'Select Extract Dacpac Settings'));
|
||||||
|
let importConfigWizardPage = sqlops.window.modelviewdialog.createWizardPage(localize('dacFx.importConfigPageName', 'Select Import Bacpac Settings'));
|
||||||
|
let exportConfigWizardPage = sqlops.window.modelviewdialog.createWizardPage(localize('dacFx.exportConfigPageName', 'Select Export Bacpac Settings'));
|
||||||
|
|
||||||
|
this.pages.set('selectOperation', new Page(selectOperationWizardPage));
|
||||||
|
this.pages.set('deployConfig', new Page(deployConfigWizardPage));
|
||||||
|
this.pages.set('extractConfig', new Page(extractConfigWizardPage));
|
||||||
|
this.pages.set('importConfig', new Page(importConfigWizardPage));
|
||||||
|
this.pages.set('exportConfig', new Page(exportConfigWizardPage));
|
||||||
|
this.pages.set('summary', new Page(summaryWizardPage));
|
||||||
|
|
||||||
|
selectOperationWizardPage.registerContent(async (view) => {
|
||||||
|
let selectOperationDacFxPage = new SelectOperationPage(this, selectOperationWizardPage, this.model, view);
|
||||||
|
this.pages.get('selectOperation').dacFxPage = selectOperationDacFxPage;
|
||||||
|
await selectOperationDacFxPage.start().then(() => {
|
||||||
|
selectOperationDacFxPage.setupNavigationValidator();
|
||||||
|
selectOperationDacFxPage.onPageEnter();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
deployConfigWizardPage.registerContent(async (view) => {
|
||||||
|
let deployConfigDacFxPage = new DeployConfigPage(this, deployConfigWizardPage, this.model, view);
|
||||||
|
this.pages.get('deployConfig').dacFxPage = deployConfigDacFxPage;
|
||||||
|
await deployConfigDacFxPage.start();
|
||||||
|
});
|
||||||
|
|
||||||
|
extractConfigWizardPage.registerContent(async (view) => {
|
||||||
|
let extractConfigDacFxPage = new ExtractConfigPage(this, extractConfigWizardPage, this.model, view);
|
||||||
|
this.pages.get('extractConfig').dacFxPage = extractConfigDacFxPage;
|
||||||
|
await extractConfigDacFxPage.start();
|
||||||
|
});
|
||||||
|
|
||||||
|
importConfigWizardPage.registerContent(async (view) => {
|
||||||
|
let importConfigDacFxPage = new ImportConfigPage(this, importConfigWizardPage, this.model, view);
|
||||||
|
this.pages.get('importConfig').dacFxPage = importConfigDacFxPage;
|
||||||
|
await importConfigDacFxPage.start();
|
||||||
|
});
|
||||||
|
|
||||||
|
exportConfigWizardPage.registerContent(async (view) => {
|
||||||
|
let exportConfigDacFxPage = new ExportConfigPage(this, exportConfigWizardPage, this.model, view);
|
||||||
|
this.pages.get('exportConfig').dacFxPage = exportConfigDacFxPage;
|
||||||
|
await exportConfigDacFxPage.start();
|
||||||
|
});
|
||||||
|
|
||||||
|
summaryWizardPage.registerContent(async (view) => {
|
||||||
|
let summaryDacFxPage = new DacFxSummaryPage(this, summaryWizardPage, this.model, view);
|
||||||
|
this.pages.get('summary').dacFxPage = summaryDacFxPage;
|
||||||
|
await summaryDacFxPage.start();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.wizard.onPageChanged(async (event) => {
|
||||||
|
let idx = event.newPage;
|
||||||
|
let page: Page;
|
||||||
|
|
||||||
|
if (idx === 1) {
|
||||||
|
switch (this.selectedOperation) {
|
||||||
|
case Operation.deploy: {
|
||||||
|
page = this.pages.get('deployConfig');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Operation.extract: {
|
||||||
|
page = this.pages.get('extractConfig');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Operation.import: {
|
||||||
|
page = this.pages.get('importConfig');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Operation.export: {
|
||||||
|
page = this.pages.get('exportConfig');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (idx === 2) {
|
||||||
|
page = this.pages.get('summary');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page !== undefined) {
|
||||||
|
page.dacFxPage.setupNavigationValidator();
|
||||||
|
page.dacFxPage.onPageEnter();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.wizard.pages = [selectOperationWizardPage, deployConfigWizardPage, summaryWizardPage];
|
||||||
|
this.wizard.generateScriptButton.hidden = true;
|
||||||
|
this.wizard.doneButton.onClick(async () => await this.executeOperation());
|
||||||
|
|
||||||
|
this.wizard.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
public registerNavigationValidator(validator: (pageChangeInfo: sqlops.window.modelviewdialog.WizardPageChangeInfo) => boolean) {
|
||||||
|
this.wizard.registerNavigationValidator(validator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setDoneButton(operation: Operation): void {
|
||||||
|
switch (operation) {
|
||||||
|
case Operation.deploy: {
|
||||||
|
this.wizard.doneButton.label = localize('dacFx.deployButton', 'Deploy');
|
||||||
|
this.selectedOperation = Operation.deploy;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Operation.extract: {
|
||||||
|
this.wizard.doneButton.label = localize('dacFx.extractButton', 'Extract');
|
||||||
|
this.selectedOperation = Operation.extract;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Operation.import: {
|
||||||
|
this.wizard.doneButton.label = localize('dacFx.importButton', 'Import');
|
||||||
|
this.selectedOperation = Operation.import;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Operation.export: {
|
||||||
|
this.wizard.doneButton.label = localize('dacFx.exportButton', 'Export');
|
||||||
|
this.selectedOperation = Operation.export;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async executeOperation() {
|
||||||
|
switch (this.selectedOperation) {
|
||||||
|
case Operation.deploy: {
|
||||||
|
await this.deploy();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Operation.extract: {
|
||||||
|
await this.extract();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Operation.import: {
|
||||||
|
await this.import();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Operation.export: {
|
||||||
|
await this.export();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async deploy() {
|
||||||
|
let service = await DataTierApplicationWizard.getService();
|
||||||
|
let ownerUri = await sqlops.connection.getUriForConnection(this.model.server.connectionId);
|
||||||
|
|
||||||
|
let result = await service.deployDacpac(this.model.filePath, this.model.database, this.model.upgradeExisting, ownerUri, sqlops.TaskExecutionMode.execute);
|
||||||
|
if (!result || !result.success) {
|
||||||
|
vscode.window.showErrorMessage(
|
||||||
|
localize('alertData.deployErrorMessage', "Deploy failed '{0}'", result.errorMessage ? result.errorMessage : 'Unknown'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async extract() {
|
||||||
|
let service = await DataTierApplicationWizard.getService();
|
||||||
|
let ownerUri = await sqlops.connection.getUriForConnection(this.model.server.connectionId);
|
||||||
|
|
||||||
|
let result = await service.extractDacpac(this.model.database, this.model.filePath, this.model.database, this.model.version, ownerUri, sqlops.TaskExecutionMode.execute);
|
||||||
|
if (!result || !result.success) {
|
||||||
|
vscode.window.showErrorMessage(
|
||||||
|
localize('alertData.extractErrorMessage', "Extract failed '{0}'", result.errorMessage ? result.errorMessage : 'Unknown'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async export() {
|
||||||
|
let service = await DataTierApplicationWizard.getService();
|
||||||
|
let ownerUri = await sqlops.connection.getUriForConnection(this.model.server.connectionId);
|
||||||
|
|
||||||
|
let result = await service.exportBacpac(this.model.database, this.model.filePath, ownerUri, sqlops.TaskExecutionMode.execute);
|
||||||
|
if (!result || !result.success) {
|
||||||
|
vscode.window.showErrorMessage(
|
||||||
|
localize('alertData.exportErrorMessage', "Export failed '{0}'", result.errorMessage ? result.errorMessage : 'Unknown'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async import() {
|
||||||
|
let service = await DataTierApplicationWizard.getService();
|
||||||
|
let ownerUri = await sqlops.connection.getUriForConnection(this.model.server.connectionId);
|
||||||
|
|
||||||
|
let result = await service.importBacpac(this.model.filePath, this.model.database, ownerUri, sqlops.TaskExecutionMode.execute);
|
||||||
|
if (!result || !result.success) {
|
||||||
|
vscode.window.showErrorMessage(
|
||||||
|
localize('alertData.importErrorMessage', "Import failed '{0}'", result.errorMessage ? result.errorMessage : 'Unknown'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async getService(): Promise<sqlops.DacFxServicesProvider> {
|
||||||
|
let currentConnection = await sqlops.connection.getCurrentConnection();
|
||||||
|
let service = sqlops.dataprotocol.getProvider<sqlops.DacFxServicesProvider>(currentConnection.providerName, sqlops.DataProviderType.DacFxServicesProvider);
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
}
|
||||||
112
extensions/import/src/wizard/pages/dacFxSummaryPage.ts
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 * as sqlops from 'sqlops';
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
|
import { DacFxDataModel } from '../api/models';
|
||||||
|
import { DataTierApplicationWizard, Operation } from '../dataTierApplicationWizard';
|
||||||
|
import { BasePage } from '../api/basePage';
|
||||||
|
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
|
export class DacFxSummaryPage extends BasePage {
|
||||||
|
|
||||||
|
protected readonly wizardPage: sqlops.window.modelviewdialog.WizardPage;
|
||||||
|
protected readonly instance: DataTierApplicationWizard;
|
||||||
|
protected readonly model: DacFxDataModel;
|
||||||
|
protected readonly view: sqlops.ModelView;
|
||||||
|
|
||||||
|
private form: sqlops.FormContainer;
|
||||||
|
private table: sqlops.TableComponent;
|
||||||
|
private loader: sqlops.LoadingComponent;
|
||||||
|
|
||||||
|
public constructor(instance: DataTierApplicationWizard, wizardPage: sqlops.window.modelviewdialog.WizardPage, model: DacFxDataModel, view: sqlops.ModelView) {
|
||||||
|
super();
|
||||||
|
this.instance = instance;
|
||||||
|
this.wizardPage = wizardPage;
|
||||||
|
this.model = model;
|
||||||
|
this.view = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
async start(): Promise<boolean> {
|
||||||
|
this.table = this.view.modelBuilder.table().component();
|
||||||
|
this.loader = this.view.modelBuilder.loadingComponent().withItem(this.table).component();
|
||||||
|
this.form = this.view.modelBuilder.formContainer().withFormItems(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
component: this.table,
|
||||||
|
title: ''
|
||||||
|
}
|
||||||
|
]
|
||||||
|
).component();
|
||||||
|
await this.view.initializeModel(this.form);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async onPageEnter(): Promise<boolean> {
|
||||||
|
this.populateTable();
|
||||||
|
this.loader.loading = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setupNavigationValidator() {
|
||||||
|
this.instance.registerNavigationValidator(() => {
|
||||||
|
if (this.loader.loading) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private populateTable() {
|
||||||
|
let data = [];
|
||||||
|
let targetServer = localize('dacfx.targetServerName', 'Target Server');
|
||||||
|
let targetDatabase = localize('dacfx.targetDatabaseName', 'Target Database');
|
||||||
|
let sourceServer = localize('dacfx.sourceServerName', 'Source Server');
|
||||||
|
let sourceDatabase = localize('dacfx.sourceDatabaseName', 'Source Database');
|
||||||
|
let fileLocation = localize('dacfx.fileLocation', 'File Location');
|
||||||
|
|
||||||
|
switch (this.instance.selectedOperation) {
|
||||||
|
case Operation.deploy: {
|
||||||
|
data = [
|
||||||
|
[targetServer, this.model.serverName],
|
||||||
|
[fileLocation, this.model.filePath],
|
||||||
|
[targetDatabase, this.model.database]];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Operation.extract: {
|
||||||
|
data = [
|
||||||
|
[sourceServer, this.model.serverName],
|
||||||
|
[sourceDatabase, this.model.database],
|
||||||
|
[localize('dacfxExtract.version', 'Version'), this.model.version],
|
||||||
|
[fileLocation, this.model.filePath]];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Operation.import: {
|
||||||
|
data = [
|
||||||
|
[targetServer, this.model.serverName],
|
||||||
|
[fileLocation, this.model.filePath],
|
||||||
|
[targetDatabase, this.model.database]];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Operation.export: {
|
||||||
|
data = [
|
||||||
|
[sourceServer, this.model.serverName],
|
||||||
|
[sourceDatabase, this.model.database],
|
||||||
|
[fileLocation, this.model.filePath]];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.table.updateProperties({
|
||||||
|
data: data,
|
||||||
|
columns: ['Setting', 'Value'],
|
||||||
|
width: 600,
|
||||||
|
height: 200
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
190
extensions/import/src/wizard/pages/deployConfigPage.ts
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 * as sqlops from 'sqlops';
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import * as path from 'path';
|
||||||
|
import * as os from 'os';
|
||||||
|
import { DacFxDataModel } from '../api/models';
|
||||||
|
import { DataTierApplicationWizard } from '../dataTierApplicationWizard';
|
||||||
|
import { DacFxConfigPage } from '../api/dacFxConfigPage';
|
||||||
|
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
|
export class DeployConfigPage extends DacFxConfigPage {
|
||||||
|
|
||||||
|
protected readonly wizardPage: sqlops.window.modelviewdialog.WizardPage;
|
||||||
|
protected readonly instance: DataTierApplicationWizard;
|
||||||
|
protected readonly model: DacFxDataModel;
|
||||||
|
protected readonly view: sqlops.ModelView;
|
||||||
|
private databaseDropdownComponent: sqlops.FormComponent;
|
||||||
|
private databaseComponent: sqlops.FormComponent;
|
||||||
|
private formBuilder: sqlops.FormBuilder;
|
||||||
|
private form: sqlops.FormContainer;
|
||||||
|
|
||||||
|
public constructor(instance: DataTierApplicationWizard, wizardPage: sqlops.window.modelviewdialog.WizardPage, model: DacFxDataModel, view: sqlops.ModelView) {
|
||||||
|
super(instance, wizardPage, model, view);
|
||||||
|
this.fileExtension = '.bacpac';
|
||||||
|
}
|
||||||
|
|
||||||
|
async start(): Promise<boolean> {
|
||||||
|
let serverComponent = await this.createServerDropdown(true);
|
||||||
|
let fileBrowserComponent = await this.createFileBrowser();
|
||||||
|
this.databaseComponent = await this.createDatabaseTextBox();
|
||||||
|
this.databaseComponent.title = localize('dacFx.databaseNameTextBox', 'Database Name');
|
||||||
|
this.databaseDropdownComponent = await this.createDeployDatabaseDropdown();
|
||||||
|
this.databaseDropdownComponent.title = localize('dacFx.databaseNameDropdown', 'Database Name');
|
||||||
|
let radioButtons = await this.createRadiobuttons();
|
||||||
|
|
||||||
|
this.formBuilder = this.view.modelBuilder.formContainer()
|
||||||
|
.withFormItems(
|
||||||
|
[
|
||||||
|
fileBrowserComponent,
|
||||||
|
serverComponent,
|
||||||
|
radioButtons,
|
||||||
|
this.databaseDropdownComponent
|
||||||
|
], {
|
||||||
|
horizontal: true,
|
||||||
|
componentWidth: 400
|
||||||
|
});
|
||||||
|
|
||||||
|
this.form = this.formBuilder.component();
|
||||||
|
await this.view.initializeModel(this.form);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async onPageEnter(): Promise<boolean> {
|
||||||
|
let r1 = await this.populateServerDropdown();
|
||||||
|
let r2 = await this.populateDeployDatabaseDropdown();
|
||||||
|
return r1 && r2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async createFileBrowser(): Promise<sqlops.FormComponent> {
|
||||||
|
this.createFileBrowserParts();
|
||||||
|
|
||||||
|
this.fileButton.onDidClick(async (click) => {
|
||||||
|
let fileUris = await vscode.window.showOpenDialog(
|
||||||
|
{
|
||||||
|
canSelectFiles: true,
|
||||||
|
canSelectFolders: false,
|
||||||
|
canSelectMany: false,
|
||||||
|
defaultUri: vscode.Uri.file(os.homedir()),
|
||||||
|
openLabel: localize('dacFxDeploy.openFile', 'Open'),
|
||||||
|
filters: {
|
||||||
|
'dacpac Files': ['dacpac'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!fileUris || fileUris.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let fileUri = fileUris[0];
|
||||||
|
this.fileTextBox.value = fileUri.fsPath;
|
||||||
|
this.model.filePath = fileUri.fsPath;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.fileTextBox.onTextChanged(async () => {
|
||||||
|
this.model.filePath = this.fileTextBox.value;
|
||||||
|
this.databaseTextBox.value = this.generateDatabaseName(this.model.filePath);
|
||||||
|
if (!this.model.upgradeExisting) {
|
||||||
|
this.model.database = this.databaseTextBox.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
component: this.fileTextBox,
|
||||||
|
title: localize('dacFxDeploy.fileTextboxTitle', 'File Location'),
|
||||||
|
actions: [this.fileButton]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async createRadiobuttons(): Promise<sqlops.FormComponent> {
|
||||||
|
let upgradeRadioButton = this.view.modelBuilder.radioButton()
|
||||||
|
.withProperties({
|
||||||
|
name: 'updateExisting',
|
||||||
|
label: localize('dacFx.upgradeRadioButtonLabel', 'Upgrade Existing Database'),
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
let newRadioButton = this.view.modelBuilder.radioButton()
|
||||||
|
.withProperties({
|
||||||
|
name: 'updateExisting',
|
||||||
|
label: localize('dacFx.newRadioButtonLabel', 'New Database'),
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
upgradeRadioButton.onDidClick(() => {
|
||||||
|
this.model.upgradeExisting = true;
|
||||||
|
this.formBuilder.removeFormItem(this.databaseComponent);
|
||||||
|
this.formBuilder.addFormItem(this.databaseDropdownComponent, { horizontal: true, componentWidth: 400 });
|
||||||
|
this.model.database = (<sqlops.CategoryValue>this.databaseDropdown.value).name;
|
||||||
|
});
|
||||||
|
|
||||||
|
newRadioButton.onDidClick(() => {
|
||||||
|
this.model.upgradeExisting = false;
|
||||||
|
this.formBuilder.removeFormItem(this.databaseDropdownComponent);
|
||||||
|
this.formBuilder.addFormItem(this.databaseComponent, { horizontal: true, componentWidth: 400 });
|
||||||
|
this.model.database = this.databaseTextBox.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initialize with upgrade existing true
|
||||||
|
upgradeRadioButton.checked = true;
|
||||||
|
this.model.upgradeExisting = true;
|
||||||
|
|
||||||
|
let flexRadioButtonsModel = this.view.modelBuilder.flexContainer()
|
||||||
|
.withLayout({
|
||||||
|
flexFlow: 'row',
|
||||||
|
}).withItems([
|
||||||
|
upgradeRadioButton, newRadioButton]
|
||||||
|
).component();
|
||||||
|
|
||||||
|
return {
|
||||||
|
component: flexRadioButtonsModel,
|
||||||
|
title: localize('dacFx.targetDatabaseRadioButtonsTitle', 'Target Database')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async createDeployDatabaseDropdown(): Promise<sqlops.FormComponent> {
|
||||||
|
this.databaseDropdown = this.view.modelBuilder.dropDown().withProperties({
|
||||||
|
required: true
|
||||||
|
}).component();
|
||||||
|
// Handle database changes
|
||||||
|
this.databaseDropdown.onValueChanged(async () => {
|
||||||
|
this.model.database = (<sqlops.CategoryValue>this.databaseDropdown.value).name;
|
||||||
|
});
|
||||||
|
this.databaseLoader = this.view.modelBuilder.loadingComponent().withItem(this.databaseDropdown).component();
|
||||||
|
return {
|
||||||
|
component: this.databaseLoader,
|
||||||
|
title: localize('dacFx.targetDatabaseDropdownTitle', 'Database Name')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async populateDeployDatabaseDropdown(): Promise<boolean> {
|
||||||
|
this.databaseLoader.loading = true;
|
||||||
|
this.databaseDropdown.updateProperties({ values: [] });
|
||||||
|
if (!this.model.server) {
|
||||||
|
this.databaseLoader.loading = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let values = await this.getDatabaseValues();
|
||||||
|
|
||||||
|
if (this.model.database === undefined) {
|
||||||
|
this.model.database = values[0].name;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.databaseDropdown.updateProperties({
|
||||||
|
values: values
|
||||||
|
});
|
||||||
|
this.databaseLoader.loading = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private generateDatabaseName(filePath: string): string {
|
||||||
|
let result = path.parse(filePath);
|
||||||
|
return result.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
100
extensions/import/src/wizard/pages/exportConfigPage.ts
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 * as sqlops from 'sqlops';
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import { DacFxDataModel } from '../api/models';
|
||||||
|
import { DataTierApplicationWizard } from '../dataTierApplicationWizard';
|
||||||
|
import { DacFxConfigPage } from '../api/dacFxConfigPage';
|
||||||
|
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
|
export class ExportConfigPage extends DacFxConfigPage {
|
||||||
|
|
||||||
|
protected readonly wizardPage: sqlops.window.modelviewdialog.WizardPage;
|
||||||
|
protected readonly instance: DataTierApplicationWizard;
|
||||||
|
protected readonly model: DacFxDataModel;
|
||||||
|
protected readonly view: sqlops.ModelView;
|
||||||
|
|
||||||
|
private form: sqlops.FormContainer;
|
||||||
|
|
||||||
|
public constructor(instance: DataTierApplicationWizard, wizardPage: sqlops.window.modelviewdialog.WizardPage, model: DacFxDataModel, view: sqlops.ModelView) {
|
||||||
|
super(instance, wizardPage, model, view);
|
||||||
|
this.fileExtension = '.bacpac';
|
||||||
|
}
|
||||||
|
|
||||||
|
async start(): Promise<boolean> {
|
||||||
|
let databaseComponent = await this.createDatabaseDropdown();
|
||||||
|
let serverComponent = await this.createServerDropdown(false);
|
||||||
|
let fileBrowserComponent = await this.createFileBrowser();
|
||||||
|
|
||||||
|
this.form = this.view.modelBuilder.formContainer()
|
||||||
|
.withFormItems(
|
||||||
|
[
|
||||||
|
serverComponent,
|
||||||
|
databaseComponent,
|
||||||
|
fileBrowserComponent,
|
||||||
|
], {
|
||||||
|
horizontal: true,
|
||||||
|
componentWidth: 400
|
||||||
|
}).component();
|
||||||
|
await this.view.initializeModel(this.form);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async onPageEnter(): Promise<boolean> {
|
||||||
|
let r1 = await this.populateServerDropdown();
|
||||||
|
let r2 = await this.populateDatabaseDropdown();
|
||||||
|
return r1 && r2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setupNavigationValidator() {
|
||||||
|
this.instance.registerNavigationValidator(() => {
|
||||||
|
if (this.databaseLoader.loading) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async createFileBrowser(): Promise<sqlops.FormComponent> {
|
||||||
|
this.createFileBrowserParts();
|
||||||
|
|
||||||
|
// default filepath
|
||||||
|
this.fileTextBox.value = this.generateFilePath();
|
||||||
|
this.model.filePath = this.fileTextBox.value;
|
||||||
|
|
||||||
|
this.fileButton.onDidClick(async (click) => {
|
||||||
|
let fileUri = await vscode.window.showSaveDialog(
|
||||||
|
{
|
||||||
|
defaultUri: vscode.Uri.file(this.fileTextBox.value),
|
||||||
|
saveLabel: localize('dacfxExport.saveFile', 'Save'),
|
||||||
|
filters: {
|
||||||
|
'bacpac Files': ['bacpac'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!fileUri) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.fileTextBox.value = fileUri.fsPath;
|
||||||
|
this.model.filePath = fileUri.fsPath;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.fileTextBox.onTextChanged(async () => {
|
||||||
|
this.model.filePath = this.fileTextBox.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
component: this.fileTextBox,
|
||||||
|
title: localize('dacFxExport.fileTextboxTitle', 'File Location'),
|
||||||
|
actions: [this.fileButton]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
122
extensions/import/src/wizard/pages/extractConfigPage.ts
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 * as sqlops from 'sqlops';
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import { DacFxDataModel } from '../api/models';
|
||||||
|
import { DataTierApplicationWizard } from '../dataTierApplicationWizard';
|
||||||
|
import { DacFxConfigPage } from '../api/dacFxConfigPage';
|
||||||
|
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
|
export class ExtractConfigPage extends DacFxConfigPage {
|
||||||
|
|
||||||
|
protected readonly wizardPage: sqlops.window.modelviewdialog.WizardPage;
|
||||||
|
protected readonly instance: DataTierApplicationWizard;
|
||||||
|
protected readonly model: DacFxDataModel;
|
||||||
|
protected readonly view: sqlops.ModelView;
|
||||||
|
|
||||||
|
private form: sqlops.FormContainer;
|
||||||
|
private versionTextBox: sqlops.InputBoxComponent;
|
||||||
|
|
||||||
|
public constructor(instance: DataTierApplicationWizard, wizardPage: sqlops.window.modelviewdialog.WizardPage, model: DacFxDataModel, view: sqlops.ModelView) {
|
||||||
|
super(instance, wizardPage, model, view);
|
||||||
|
this.fileExtension = '.dacpac';
|
||||||
|
}
|
||||||
|
|
||||||
|
async start(): Promise<boolean> {
|
||||||
|
let databaseComponent = await this.createDatabaseDropdown();
|
||||||
|
let serverComponent = await this.createServerDropdown(false);
|
||||||
|
let fileBrowserComponent = await this.createFileBrowser();
|
||||||
|
let versionComponent = await this.createVersionTextBox();
|
||||||
|
|
||||||
|
this.form = this.view.modelBuilder.formContainer()
|
||||||
|
.withFormItems(
|
||||||
|
[
|
||||||
|
serverComponent,
|
||||||
|
databaseComponent,
|
||||||
|
versionComponent,
|
||||||
|
fileBrowserComponent,
|
||||||
|
], {
|
||||||
|
horizontal: true,
|
||||||
|
componentWidth: 400
|
||||||
|
}).component();
|
||||||
|
await this.view.initializeModel(this.form);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async onPageEnter(): Promise<boolean> {
|
||||||
|
let r1 = await this.populateServerDropdown();
|
||||||
|
let r2 = await this.populateDatabaseDropdown();
|
||||||
|
return r1 && r2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setupNavigationValidator() {
|
||||||
|
this.instance.registerNavigationValidator(() => {
|
||||||
|
if (this.databaseLoader.loading) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async createFileBrowser(): Promise<sqlops.FormComponent> {
|
||||||
|
this.createFileBrowserParts();
|
||||||
|
|
||||||
|
// default filepath
|
||||||
|
this.fileTextBox.value = this.generateFilePath();
|
||||||
|
this.model.filePath = this.fileTextBox.value;
|
||||||
|
|
||||||
|
this.fileButton.onDidClick(async (click) => {
|
||||||
|
let fileUri = await vscode.window.showSaveDialog(
|
||||||
|
{
|
||||||
|
defaultUri: vscode.Uri.file(this.fileTextBox.value),
|
||||||
|
saveLabel: localize('dacfxExtract.saveFile', 'Save'),
|
||||||
|
filters: {
|
||||||
|
'dacpac Files': ['dacpac'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!fileUri) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.fileTextBox.value = fileUri.fsPath;
|
||||||
|
this.model.filePath = fileUri.fsPath;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.fileTextBox.onTextChanged(async () => {
|
||||||
|
this.model.filePath = this.fileTextBox.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
component: this.fileTextBox,
|
||||||
|
title: localize('dacFxExtract.fileTextboxTitle', 'File Location'),
|
||||||
|
actions: [this.fileButton]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async createVersionTextBox(): Promise<sqlops.FormComponent> {
|
||||||
|
this.versionTextBox = this.view.modelBuilder.inputBox().withProperties({
|
||||||
|
required: true
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
// default filepath
|
||||||
|
this.versionTextBox.value = '1.0.0.0';
|
||||||
|
this.model.version = this.versionTextBox.value;
|
||||||
|
|
||||||
|
this.versionTextBox.onTextChanged(async () => {
|
||||||
|
this.model.version = this.versionTextBox.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
component: this.versionTextBox,
|
||||||
|
title: localize('dacFxExtract.versionTextboxTitle', 'Version (use x.x.x.x where x is a number)'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -102,57 +102,9 @@ export class FileConfigPage extends ImportPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async populateServerDropdown(): Promise<boolean> {
|
private async populateServerDropdown(): Promise<boolean> {
|
||||||
let cons = await sqlops.connection.getActiveConnections();
|
let values = await this.getServerValues();
|
||||||
// This user has no active connections ABORT MISSION
|
if (values === undefined) {
|
||||||
if (!cons || cons.length === 0) {
|
return false;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let count = -1;
|
|
||||||
let idx = -1;
|
|
||||||
|
|
||||||
|
|
||||||
let values = cons.map(c => {
|
|
||||||
// Handle the code to remember what the user's choice was from before
|
|
||||||
count++;
|
|
||||||
if (idx === -1) {
|
|
||||||
if (this.model.server && c.connectionId === this.model.server.connectionId) {
|
|
||||||
idx = count;
|
|
||||||
} else if (this.model.serverId && c.connectionId === this.model.serverId) {
|
|
||||||
idx = count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let db = c.options.databaseDisplayName;
|
|
||||||
let usr = c.options.user;
|
|
||||||
let srv = c.options.server;
|
|
||||||
|
|
||||||
if (!db) {
|
|
||||||
db = '<default>';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!usr) {
|
|
||||||
usr = 'default';
|
|
||||||
}
|
|
||||||
|
|
||||||
let finalName = `${srv}, ${db} (${usr})`;
|
|
||||||
return {
|
|
||||||
connection: c,
|
|
||||||
displayName: finalName,
|
|
||||||
name: c.connectionId
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
if (idx >= 0) {
|
|
||||||
let tmp = values[0];
|
|
||||||
values[0] = values[idx];
|
|
||||||
values[idx] = tmp;
|
|
||||||
} else {
|
|
||||||
delete this.model.server;
|
|
||||||
delete this.model.serverId;
|
|
||||||
delete this.model.database;
|
|
||||||
delete this.model.schema;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.model.server = values[0].connection;
|
this.model.server = values[0].connection;
|
||||||
@@ -195,29 +147,7 @@ export class FileConfigPage extends ImportPage {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let values = await this.getDatabaseValues();
|
||||||
let idx = -1;
|
|
||||||
let count = -1;
|
|
||||||
let values = (await sqlops.connection.listDatabases(this.model.server.connectionId)).map(db => {
|
|
||||||
count++;
|
|
||||||
if (this.model.database && db === this.model.database) {
|
|
||||||
idx = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
displayName: db,
|
|
||||||
name: db
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
if (idx >= 0) {
|
|
||||||
let tmp = values[0];
|
|
||||||
values[0] = values[idx];
|
|
||||||
values[idx] = tmp;
|
|
||||||
} else {
|
|
||||||
delete this.model.database;
|
|
||||||
delete this.model.schema;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.model.database = values[0].name;
|
this.model.database = values[0].name;
|
||||||
|
|
||||||
@@ -377,6 +307,18 @@ export class FileConfigPage extends ImportPage {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected deleteServerValues() {
|
||||||
|
delete this.model.server;
|
||||||
|
delete this.model.serverId;
|
||||||
|
delete this.model.database;
|
||||||
|
delete this.model.schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected deleteDatabaseValues() {
|
||||||
|
delete this.model.database;
|
||||||
|
delete this.model.schema;
|
||||||
|
}
|
||||||
|
|
||||||
// private async populateTableNames(): Promise<boolean> {
|
// private async populateTableNames(): Promise<boolean> {
|
||||||
// this.tableNames = [];
|
// this.tableNames = [];
|
||||||
// let databaseName = (<sqlops.CategoryValue>this.databaseDropdown.value).name;
|
// let databaseName = (<sqlops.CategoryValue>this.databaseDropdown.value).name;
|
||||||
|
|||||||
101
extensions/import/src/wizard/pages/importConfigPage.ts
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 * as sqlops from 'sqlops';
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import * as path from 'path';
|
||||||
|
import * as os from 'os';
|
||||||
|
import { DacFxDataModel } from '../api/models';
|
||||||
|
import { DataTierApplicationWizard } from '../dataTierApplicationWizard';
|
||||||
|
import { DacFxConfigPage } from '../api/dacFxConfigPage';
|
||||||
|
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
|
export class ImportConfigPage extends DacFxConfigPage {
|
||||||
|
|
||||||
|
protected readonly wizardPage: sqlops.window.modelviewdialog.WizardPage;
|
||||||
|
protected readonly instance: DataTierApplicationWizard;
|
||||||
|
protected readonly model: DacFxDataModel;
|
||||||
|
protected readonly view: sqlops.ModelView;
|
||||||
|
|
||||||
|
private form: sqlops.FormContainer;
|
||||||
|
|
||||||
|
public constructor(instance: DataTierApplicationWizard, wizardPage: sqlops.window.modelviewdialog.WizardPage, model: DacFxDataModel, view: sqlops.ModelView) {
|
||||||
|
super(instance, wizardPage, model, view);
|
||||||
|
this.fileExtension = '.bacpac';
|
||||||
|
}
|
||||||
|
|
||||||
|
async start(): Promise<boolean> {
|
||||||
|
let databaseComponent = await this.createDatabaseTextBox();
|
||||||
|
let serverComponent = await this.createServerDropdown(true);
|
||||||
|
let fileBrowserComponent = await this.createFileBrowser();
|
||||||
|
|
||||||
|
this.form = this.view.modelBuilder.formContainer()
|
||||||
|
.withFormItems(
|
||||||
|
[
|
||||||
|
fileBrowserComponent,
|
||||||
|
serverComponent,
|
||||||
|
databaseComponent,
|
||||||
|
], {
|
||||||
|
horizontal: true,
|
||||||
|
componentWidth: 400
|
||||||
|
}).component();
|
||||||
|
await this.view.initializeModel(this.form);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async onPageEnter(): Promise<boolean> {
|
||||||
|
let r1 = await this.populateServerDropdown();
|
||||||
|
return r1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async createFileBrowser(): Promise<sqlops.FormComponent> {
|
||||||
|
this.createFileBrowserParts();
|
||||||
|
|
||||||
|
this.fileButton.onDidClick(async (click) => {
|
||||||
|
let fileUris = await vscode.window.showOpenDialog(
|
||||||
|
{
|
||||||
|
canSelectFiles: true,
|
||||||
|
canSelectFolders: false,
|
||||||
|
canSelectMany: false,
|
||||||
|
defaultUri: vscode.Uri.file(os.homedir()),
|
||||||
|
openLabel: localize('dacFxImport.openFile', 'Open'),
|
||||||
|
filters: {
|
||||||
|
'bacpac Files': ['bacpac'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!fileUris || fileUris.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let fileUri = fileUris[0];
|
||||||
|
this.fileTextBox.value = fileUri.fsPath;
|
||||||
|
this.model.filePath = fileUri.fsPath;
|
||||||
|
this.model.database = this.generateDatabaseName(this.model.filePath);
|
||||||
|
this.databaseTextBox.value = this.model.database;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.fileTextBox.onTextChanged(async () => {
|
||||||
|
this.model.filePath = this.fileTextBox.value;
|
||||||
|
this.model.database = this.generateDatabaseName(this.model.filePath);
|
||||||
|
this.databaseTextBox.value = this.model.database;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
component: this.fileTextBox,
|
||||||
|
title: localize('dacFxImport.fileTextboxTitle', 'File Location'),
|
||||||
|
actions: [this.fileButton]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private generateDatabaseName(filePath: string): string {
|
||||||
|
let result = path.parse(filePath);
|
||||||
|
return result.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
174
extensions/import/src/wizard/pages/selectOperationpage.ts
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 * as sqlops from 'sqlops';
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
|
import { DacFxDataModel } from '../api/models';
|
||||||
|
import { DataTierApplicationWizard, Operation } from '../dataTierApplicationWizard';
|
||||||
|
import { BasePage } from '../api/basePage';
|
||||||
|
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
|
export class SelectOperationPage extends BasePage {
|
||||||
|
|
||||||
|
protected readonly wizardPage: sqlops.window.modelviewdialog.WizardPage;
|
||||||
|
protected readonly instance: DataTierApplicationWizard;
|
||||||
|
protected readonly model: DacFxDataModel;
|
||||||
|
protected readonly view: sqlops.ModelView;
|
||||||
|
|
||||||
|
private deployRadioButton: sqlops.RadioButtonComponent;
|
||||||
|
private extractRadioButton: sqlops.RadioButtonComponent;
|
||||||
|
private importRadioButton: sqlops.RadioButtonComponent;
|
||||||
|
private exportRadioButton: sqlops.RadioButtonComponent;
|
||||||
|
private form: sqlops.FormContainer;
|
||||||
|
|
||||||
|
public constructor(instance: DataTierApplicationWizard, wizardPage: sqlops.window.modelviewdialog.WizardPage, model: DacFxDataModel, view: sqlops.ModelView) {
|
||||||
|
super();
|
||||||
|
this.instance = instance;
|
||||||
|
this.wizardPage = wizardPage;
|
||||||
|
this.model = model;
|
||||||
|
this.view = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
async start(): Promise<boolean> {
|
||||||
|
let deployComponent = await this.createDeployRadioButton();
|
||||||
|
let extractComponent = await this.createExtractRadioButton();
|
||||||
|
let importComponent = await this.createImportRadioButton();
|
||||||
|
let exportComponent = await this.createExportRadioButton();
|
||||||
|
|
||||||
|
this.form = this.view.modelBuilder.formContainer()
|
||||||
|
.withFormItems(
|
||||||
|
[
|
||||||
|
deployComponent,
|
||||||
|
extractComponent,
|
||||||
|
importComponent,
|
||||||
|
exportComponent
|
||||||
|
], {
|
||||||
|
horizontal: true
|
||||||
|
}).component();
|
||||||
|
await this.view.initializeModel(this.form);
|
||||||
|
|
||||||
|
// default have the first radio button checked
|
||||||
|
this.deployRadioButton.checked = true;
|
||||||
|
this.instance.setDoneButton(Operation.deploy);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async onPageEnter(): Promise<boolean> {
|
||||||
|
let numPages = this.instance.wizard.pages.length;
|
||||||
|
for (let i = numPages - 1; i > 2; --i) {
|
||||||
|
await this.instance.wizard.removePage(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async createDeployRadioButton(): Promise<sqlops.FormComponent> {
|
||||||
|
this.deployRadioButton = this.view.modelBuilder.radioButton()
|
||||||
|
.withProperties({
|
||||||
|
name: 'selectedOperation',
|
||||||
|
label: localize('dacFx.deployRadioButtonLabel', 'Deploy a data-tier application .dacpac file to an instance of SQL Server [Deploy Dacpac]'),
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this.deployRadioButton.onDidClick(() => {
|
||||||
|
// remove the previous page
|
||||||
|
this.instance.wizard.removePage(1);
|
||||||
|
|
||||||
|
// add deploy page
|
||||||
|
let page = this.instance.pages.get('deployConfig');
|
||||||
|
this.instance.wizard.addPage(page.wizardPage, 1);
|
||||||
|
|
||||||
|
// change button text and operation
|
||||||
|
this.instance.setDoneButton(Operation.deploy);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
component: this.deployRadioButton,
|
||||||
|
title: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async createExtractRadioButton(): Promise<sqlops.FormComponent> {
|
||||||
|
this.extractRadioButton = this.view.modelBuilder.radioButton()
|
||||||
|
.withProperties({
|
||||||
|
name: 'selectedOperation',
|
||||||
|
label: localize('dacFx.extractRadioButtonLabel', 'Extract a data-tier application from an instance of SQL Server to a .dacpac file [Extract Dacpac]'),
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this.extractRadioButton.onDidClick(() => {
|
||||||
|
// remove the previous pages
|
||||||
|
this.instance.wizard.removePage(1);
|
||||||
|
|
||||||
|
// add the extract page
|
||||||
|
let page = this.instance.pages.get('extractConfig');
|
||||||
|
this.instance.wizard.addPage(page.wizardPage, 1);
|
||||||
|
|
||||||
|
// change button text and operation
|
||||||
|
this.instance.setDoneButton(Operation.extract);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
component: this.extractRadioButton,
|
||||||
|
title: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async createImportRadioButton(): Promise<sqlops.FormComponent> {
|
||||||
|
this.importRadioButton = this.view.modelBuilder.radioButton()
|
||||||
|
.withProperties({
|
||||||
|
name: 'selectedOperation',
|
||||||
|
label: localize('dacFx.importRadioButtonLabel', 'Create a database from a .bacpac file [Import Bacpac]'),
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this.importRadioButton.onDidClick(() => {
|
||||||
|
// remove the previous page
|
||||||
|
this.instance.wizard.removePage(1);
|
||||||
|
|
||||||
|
// add the import page
|
||||||
|
let page = this.instance.pages.get('importConfig');
|
||||||
|
this.instance.wizard.addPage(page.wizardPage, 1);
|
||||||
|
|
||||||
|
// change button text and operation
|
||||||
|
this.instance.setDoneButton(Operation.import);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
component: this.importRadioButton,
|
||||||
|
title: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async createExportRadioButton(): Promise<sqlops.FormComponent> {
|
||||||
|
this.exportRadioButton = this.view.modelBuilder.radioButton()
|
||||||
|
.withProperties({
|
||||||
|
name: 'selectedOperation',
|
||||||
|
label: localize('dacFx.exportRadioButtonLabel', 'Export the schema and data from a database to the logical .bacpac file format [Export Bacpac]'),
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this.exportRadioButton.onDidClick(() => {
|
||||||
|
// remove the 2 previous pages
|
||||||
|
this.instance.wizard.removePage(1);
|
||||||
|
|
||||||
|
// add the export pages
|
||||||
|
let page = this.instance.pages.get('exportConfig');
|
||||||
|
this.instance.wizard.addPage(page.wizardPage, 1);
|
||||||
|
|
||||||
|
// change button text and operation
|
||||||
|
this.instance.setDoneButton(Operation.export);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
component: this.exportRadioButton,
|
||||||
|
title: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public setupNavigationValidator() {
|
||||||
|
this.instance.registerNavigationValidator(() => {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,8 @@ agent-base@4, agent-base@^4.1.0:
|
|||||||
|
|
||||||
applicationinsights@1.0.1:
|
applicationinsights@1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.npmjs.org/applicationinsights/-/applicationinsights-1.0.1.tgz#53446b830fe8d5d619eee2a278b31d3d25030927"
|
resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.1.tgz#53446b830fe8d5d619eee2a278b31d3d25030927"
|
||||||
|
integrity sha1-U0Rrgw/o1dYZ7uKieLMdPSUDCSc=
|
||||||
dependencies:
|
dependencies:
|
||||||
diagnostic-channel "0.2.0"
|
diagnostic-channel "0.2.0"
|
||||||
diagnostic-channel-publishers "0.2.1"
|
diagnostic-channel-publishers "0.2.1"
|
||||||
@@ -35,7 +36,7 @@ buffer-alloc-unsafe@^1.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
|
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
|
||||||
integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
|
integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
|
||||||
|
|
||||||
buffer-alloc@^1.1.0:
|
buffer-alloc@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
|
resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
|
||||||
integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
|
integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
|
||||||
@@ -74,19 +75,26 @@ core-util-is@~1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||||
|
|
||||||
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.2.7":
|
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.2.10":
|
||||||
version "0.2.6"
|
version "0.2.10"
|
||||||
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/85653d8b305af8aef334728d71f07bdc240dfcb7"
|
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/4de3f7caf0eba54159911b977ddb4f5d7c0a9ca8"
|
||||||
dependencies:
|
dependencies:
|
||||||
vscode-languageclient "3.5.1"
|
vscode-languageclient "3.5.1"
|
||||||
|
|
||||||
debug@3.1.0, debug@^3.1.0:
|
debug@3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
||||||
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
|
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
|
||||||
dependencies:
|
dependencies:
|
||||||
ms "2.0.0"
|
ms "2.0.0"
|
||||||
|
|
||||||
|
debug@^3.1.0:
|
||||||
|
version "3.2.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
|
||||||
|
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
|
||||||
|
dependencies:
|
||||||
|
ms "^2.1.1"
|
||||||
|
|
||||||
decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1:
|
decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1"
|
resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1"
|
||||||
@@ -142,11 +150,13 @@ decompress@^4.2.0:
|
|||||||
|
|
||||||
diagnostic-channel-publishers@0.2.1:
|
diagnostic-channel-publishers@0.2.1:
|
||||||
version "0.2.1"
|
version "0.2.1"
|
||||||
resolved "https://registry.npmjs.org/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3"
|
resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3"
|
||||||
|
integrity sha1-ji1geottef6IC1SLxYzGvrKIxPM=
|
||||||
|
|
||||||
diagnostic-channel@0.2.0:
|
diagnostic-channel@0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.npmjs.org/diagnostic-channel/-/diagnostic-channel-0.2.0.tgz#cc99af9612c23fb1fff13612c72f2cbfaa8d5a17"
|
resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-0.2.0.tgz#cc99af9612c23fb1fff13612c72f2cbfaa8d5a17"
|
||||||
|
integrity sha1-zJmvlhLCP7H/8TYSxy8sv6qNWhc=
|
||||||
dependencies:
|
dependencies:
|
||||||
semver "^5.3.0"
|
semver "^5.3.0"
|
||||||
|
|
||||||
@@ -158,9 +168,9 @@ end-of-stream@^1.0.0:
|
|||||||
once "^1.4.0"
|
once "^1.4.0"
|
||||||
|
|
||||||
es6-promise@^4.0.3:
|
es6-promise@^4.0.3:
|
||||||
version "4.2.4"
|
version "4.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29"
|
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.5.tgz#da6d0d5692efb461e082c14817fe2427d8f5d054"
|
||||||
integrity sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==
|
integrity sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==
|
||||||
|
|
||||||
es6-promisify@^5.0.0:
|
es6-promisify@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
@@ -210,9 +220,9 @@ get-stream@^2.2.0:
|
|||||||
pinkie-promise "^2.0.0"
|
pinkie-promise "^2.0.0"
|
||||||
|
|
||||||
graceful-fs@^4.1.10:
|
graceful-fs@^4.1.10:
|
||||||
version "4.1.11"
|
version "4.1.15"
|
||||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
|
||||||
integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=
|
integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
|
||||||
|
|
||||||
"graceful-readlink@>= 1.0.0":
|
"graceful-readlink@>= 1.0.0":
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
@@ -284,6 +294,11 @@ ms@2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||||
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
|
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
|
||||||
|
|
||||||
|
ms@^2.1.1:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
|
||||||
|
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
|
||||||
|
|
||||||
object-assign@^4.0.1:
|
object-assign@^4.0.1:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||||
@@ -297,9 +312,9 @@ once@^1.4.0:
|
|||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
opener@^1.4.3:
|
opener@^1.4.3:
|
||||||
version "1.4.3"
|
version "1.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8"
|
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed"
|
||||||
integrity sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=
|
integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==
|
||||||
|
|
||||||
os-tmpdir@~1.0.2:
|
os-tmpdir@~1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
@@ -365,7 +380,8 @@ seek-bzip@^1.0.5:
|
|||||||
|
|
||||||
semver@^5.3.0:
|
semver@^5.3.0:
|
||||||
version "5.6.0"
|
version "5.6.0"
|
||||||
resolved "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
|
||||||
|
integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
|
||||||
|
|
||||||
"service-downloader@github:anthonydresser/service-downloader#0.1.5":
|
"service-downloader@github:anthonydresser/service-downloader#0.1.5":
|
||||||
version "0.1.5"
|
version "0.1.5"
|
||||||
@@ -393,16 +409,16 @@ strip-dirs@^2.0.0:
|
|||||||
is-natural-number "^4.0.1"
|
is-natural-number "^4.0.1"
|
||||||
|
|
||||||
tar-stream@^1.5.2:
|
tar-stream@^1.5.2:
|
||||||
version "1.6.1"
|
version "1.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.1.tgz#f84ef1696269d6223ca48f6e1eeede3f7e81f395"
|
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555"
|
||||||
integrity sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==
|
integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==
|
||||||
dependencies:
|
dependencies:
|
||||||
bl "^1.0.0"
|
bl "^1.0.0"
|
||||||
buffer-alloc "^1.1.0"
|
buffer-alloc "^1.2.0"
|
||||||
end-of-stream "^1.0.0"
|
end-of-stream "^1.0.0"
|
||||||
fs-constants "^1.0.0"
|
fs-constants "^1.0.0"
|
||||||
readable-stream "^2.3.0"
|
readable-stream "^2.3.0"
|
||||||
to-buffer "^1.1.0"
|
to-buffer "^1.1.1"
|
||||||
xtend "^4.0.0"
|
xtend "^4.0.0"
|
||||||
|
|
||||||
through@^2.3.6:
|
through@^2.3.6:
|
||||||
@@ -417,15 +433,15 @@ tmp@^0.0.33:
|
|||||||
dependencies:
|
dependencies:
|
||||||
os-tmpdir "~1.0.2"
|
os-tmpdir "~1.0.2"
|
||||||
|
|
||||||
to-buffer@^1.1.0:
|
to-buffer@^1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
|
resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
|
||||||
integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==
|
integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==
|
||||||
|
|
||||||
unbzip2-stream@^1.0.9:
|
unbzip2-stream@^1.0.9:
|
||||||
version "1.2.5"
|
version "1.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz#73a033a567bbbde59654b193c44d48a7e4f43c47"
|
resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz#7854da51622a7e63624221196357803b552966a1"
|
||||||
integrity sha512-izD3jxT8xkzwtXRUZjtmRwKnZoeECrfZ8ra/ketwOcusbZEp4mjULMnJOCfTDZBgGQAAY1AJ/IgxcwkavcX9Og==
|
integrity sha512-fIZnvdjblYs7Cru/xC6tCPVhz7JkYcVQQkePwMLyQELzYTds2Xn8QefPVnvdVhhZqubxNA1cASXEH5wcK0Bucw==
|
||||||
dependencies:
|
dependencies:
|
||||||
buffer "^3.0.1"
|
buffer "^3.0.1"
|
||||||
through "^2.3.6"
|
through "^2.3.6"
|
||||||
@@ -437,7 +453,8 @@ util-deprecate@~1.0.1:
|
|||||||
|
|
||||||
vscode-extension-telemetry@0.0.18:
|
vscode-extension-telemetry@0.0.18:
|
||||||
version "0.0.18"
|
version "0.0.18"
|
||||||
resolved "https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.18.tgz#602ba20d8c71453aa34533a291e7638f6e5c0327"
|
resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.18.tgz#602ba20d8c71453aa34533a291e7638f6e5c0327"
|
||||||
|
integrity sha512-Vw3Sr+dZwl+c6PlsUwrTtCOJkgrmvS3OUVDQGcmpXWAgq9xGq6as0K4pUx+aGqTjzLAESmWSrs6HlJm6J6Khcg==
|
||||||
dependencies:
|
dependencies:
|
||||||
applicationinsights "1.0.1"
|
applicationinsights "1.0.1"
|
||||||
|
|
||||||
@@ -467,9 +484,9 @@ vscode-languageserver-types@3.5.0:
|
|||||||
integrity sha1-5I15li8LjgLelV4/UkkI4rGcA3Q=
|
integrity sha1-5I15li8LjgLelV4/UkkI4rGcA3Q=
|
||||||
|
|
||||||
vscode-nls@^3.2.1:
|
vscode-nls@^3.2.1:
|
||||||
version "3.2.4"
|
version "3.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"
|
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.5.tgz#25520c1955108036dec607c85e00a522f247f1a4"
|
||||||
integrity sha512-FTjdqa4jDDoBjJqr36O8lmmZf/55kQ2w4ZY/+GL6K92fq765BqO3aYw21atnXUno/P04V5DWagNl4ybDIndJsw==
|
integrity sha512-ITtoh3V4AkWXMmp3TB97vsMaHRgHhsSFPsUdzlueSL+dRZbSNTZeOmdQv60kjCV306ghPxhDeoNUEm3+EZMuyw==
|
||||||
|
|
||||||
wrappy@1:
|
wrappy@1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
@@ -491,4 +508,5 @@ yauzl@^2.4.2:
|
|||||||
|
|
||||||
zone.js@0.7.6:
|
zone.js@0.7.6:
|
||||||
version "0.7.6"
|
version "0.7.6"
|
||||||
resolved "https://registry.npmjs.org/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009"
|
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009"
|
||||||
|
integrity sha1-+7w50+AmHQmG8boGMG6zrrDSIAk=
|
||||||
|
|||||||
@@ -23,7 +23,8 @@
|
|||||||
"onCommand:markdown.showLockedPreviewToSide",
|
"onCommand:markdown.showLockedPreviewToSide",
|
||||||
"onCommand:markdown.showSource",
|
"onCommand:markdown.showSource",
|
||||||
"onCommand:markdown.showPreviewSecuritySelector",
|
"onCommand:markdown.showPreviewSecuritySelector",
|
||||||
"onWebviewPanel:markdown.preview"
|
"onWebviewPanel:markdown.preview",
|
||||||
|
"onCommand:notebook.showPreview"
|
||||||
],
|
],
|
||||||
"contributes": {
|
"contributes": {
|
||||||
"commands": [
|
"commands": [
|
||||||
@@ -77,6 +78,11 @@
|
|||||||
"command": "markdown.preview.toggleLock",
|
"command": "markdown.preview.toggleLock",
|
||||||
"title": "%markdown.preview.toggleLock.title%",
|
"title": "%markdown.preview.toggleLock.title%",
|
||||||
"category": "Markdown"
|
"category": "Markdown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "notebook.showPreview",
|
||||||
|
"title": "notebook.showPreview",
|
||||||
|
"category": "Notebook"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"menus": {
|
"menus": {
|
||||||
@@ -154,6 +160,10 @@
|
|||||||
{
|
{
|
||||||
"command": "markdown.preview.toggleLock",
|
"command": "markdown.preview.toggleLock",
|
||||||
"when": "markdownPreviewFocus"
|
"when": "markdownPreviewFocus"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "notebook.showPreview",
|
||||||
|
"when": "false"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ import * as vscode from 'vscode';
|
|||||||
export interface Command {
|
export interface Command {
|
||||||
readonly id: string;
|
readonly id: string;
|
||||||
|
|
||||||
execute(...args: any[]): void;
|
// {{SQL CARBON EDIT}}
|
||||||
|
execute(...args: any[]): any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CommandManager {
|
export class CommandManager {
|
||||||
@@ -26,7 +27,8 @@ export class CommandManager {
|
|||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
private registerCommand(id: string, impl: (...args: any[]) => void, thisArg?: any) {
|
// {{SQL CARBON EDIT}}
|
||||||
|
private registerCommand(id: string, impl: (...args: any[]) => any, thisArg?: any) {
|
||||||
if (this.commands.has(id)) {
|
if (this.commands.has(id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,3 +11,5 @@ export { RefreshPreviewCommand } from './refreshPreview';
|
|||||||
export { ShowPreviewSecuritySelectorCommand } from './showPreviewSecuritySelector';
|
export { ShowPreviewSecuritySelectorCommand } from './showPreviewSecuritySelector';
|
||||||
export { MoveCursorToPositionCommand } from './moveCursorToPosition';
|
export { MoveCursorToPositionCommand } from './moveCursorToPosition';
|
||||||
export { ToggleLockCommand } from './toggleLock';
|
export { ToggleLockCommand } from './toggleLock';
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
export { ShowNotebookPreview } from './showNotebookPreview';
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
|
||||||
|
import { Command } from '../commandManager';
|
||||||
|
import { MarkdownEngine } from '../markdownEngine';
|
||||||
|
|
||||||
|
export class ShowNotebookPreview implements Command {
|
||||||
|
public readonly id = 'notebook.showPreview';
|
||||||
|
|
||||||
|
public constructor(
|
||||||
|
private readonly engine: MarkdownEngine
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public async execute(document: vscode.Uri, textContent: string): Promise<string> {
|
||||||
|
return this.engine.renderText(document, textContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -59,6 +59,8 @@ export function activate(context: vscode.ExtensionContext) {
|
|||||||
commandManager.register(new commands.OnPreviewStyleLoadErrorCommand());
|
commandManager.register(new commands.OnPreviewStyleLoadErrorCommand());
|
||||||
commandManager.register(new commands.OpenDocumentLinkCommand(engine));
|
commandManager.register(new commands.OpenDocumentLinkCommand(engine));
|
||||||
commandManager.register(new commands.ToggleLockCommand(previewManager));
|
commandManager.register(new commands.ToggleLockCommand(previewManager));
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
commandManager.register(new commands.ShowNotebookPreview(engine));
|
||||||
|
|
||||||
context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(() => {
|
context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(() => {
|
||||||
logger.updateConfiguration();
|
logger.updateConfiguration();
|
||||||
|
|||||||
@@ -86,6 +86,12 @@ export class MarkdownEngine {
|
|||||||
return { text, offset };
|
return { text, offset };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
public async renderText(document: vscode.Uri, text: string): Promise<string> {
|
||||||
|
const engine = await this.getEngine(document);
|
||||||
|
return engine.render(text);
|
||||||
|
}
|
||||||
|
|
||||||
public async render(document: vscode.Uri, stripFrontmatter: boolean, text: string): Promise<string> {
|
public async render(document: vscode.Uri, stripFrontmatter: boolean, text: string): Promise<string> {
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
if (stripFrontmatter) {
|
if (stripFrontmatter) {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
"update-grammar": "node ../../build/npm/update-grammar.js Microsoft/vscode-mssql syntaxes/SQL.plist ./syntaxes/sql.tmLanguage.json"
|
"update-grammar": "node ../../build/npm/update-grammar.js Microsoft/vscode-mssql syntaxes/SQL.plist ./syntaxes/sql.tmLanguage.json"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.2.8",
|
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.2.10",
|
||||||
"opener": "^1.4.3",
|
"opener": "^1.4.3",
|
||||||
"service-downloader": "github:anthonydresser/service-downloader#0.1.5",
|
"service-downloader": "github:anthonydresser/service-downloader#0.1.5",
|
||||||
"vscode-extension-telemetry": "^0.0.15"
|
"vscode-extension-telemetry": "^0.0.15"
|
||||||
@@ -285,6 +285,10 @@
|
|||||||
{
|
{
|
||||||
"displayName": "Windows Authentication",
|
"displayName": "Windows Authentication",
|
||||||
"name": "Integrated"
|
"name": "Integrated"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "Azure Active Directory - Universal with MFA support",
|
||||||
|
"name": "AzureMFA"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"isRequired": true,
|
"isRequired": true,
|
||||||
|
|||||||
@@ -163,6 +163,7 @@
|
|||||||
"\tFROM INFORMATION_SCHEMA.ROUTINES",
|
"\tFROM INFORMATION_SCHEMA.ROUTINES",
|
||||||
"WHERE SPECIFIC_SCHEMA = N'${2:dbo}'",
|
"WHERE SPECIFIC_SCHEMA = N'${2:dbo}'",
|
||||||
"\tAND SPECIFIC_NAME = N'${1:StoredProcedureName}'",
|
"\tAND SPECIFIC_NAME = N'${1:StoredProcedureName}'",
|
||||||
|
"\tAND ROUTINE_TYPE = N'PROCEDURE'"
|
||||||
")",
|
")",
|
||||||
"DROP PROCEDURE ${2:dbo}.${1:StoredProcedureName}",
|
"DROP PROCEDURE ${2:dbo}.${1:StoredProcedureName}",
|
||||||
"GO",
|
"GO",
|
||||||
|
|||||||
@@ -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.52",
|
"version": "1.5.0-alpha.63",
|
||||||
"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",
|
||||||
|
|||||||
@@ -291,3 +291,60 @@ export namespace DeleteAgentJobScheduleRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------- < Agent Management > ------------------------------------
|
// ------------------------------- < Agent Management > ------------------------------------
|
||||||
|
|
||||||
|
// ------------------------------- < DacFx > ------------------------------------
|
||||||
|
|
||||||
|
export enum TaskExecutionMode {
|
||||||
|
execute = 0,
|
||||||
|
script = 1,
|
||||||
|
executeAndScript = 2,
|
||||||
|
}
|
||||||
|
export interface ExportParams {
|
||||||
|
databaseName: string;
|
||||||
|
packageFilePath: string;
|
||||||
|
ownerUri: string;
|
||||||
|
taskExecutionMode: TaskExecutionMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ImportParams {
|
||||||
|
packageFilePath: string;
|
||||||
|
databaseName: string;
|
||||||
|
ownerUri: string;
|
||||||
|
taskExecutionMode: TaskExecutionMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface ExtractParams {
|
||||||
|
databaseName: string;
|
||||||
|
packageFilePath: string;
|
||||||
|
applicationName: string;
|
||||||
|
applicationVersion: string;
|
||||||
|
ownerUri: string;
|
||||||
|
taskExecutionMode: TaskExecutionMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeployParams {
|
||||||
|
packageFilePath: string;
|
||||||
|
databaseName: string;
|
||||||
|
upgradeExisting: boolean;
|
||||||
|
ownerUri: string;
|
||||||
|
taskExecutionMode: TaskExecutionMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace ExportRequest {
|
||||||
|
export const type = new RequestType<ExportParams, sqlops.DacFxResult, void, void>('dacfx/export');
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace ImportRequest {
|
||||||
|
export const type = new RequestType<ImportParams, sqlops.DacFxResult, void, void>('dacfx/import');
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace ExtractRequest {
|
||||||
|
export const type = new RequestType<ExtractParams, sqlops.DacFxResult, void, void>('dacfx/extract');
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace DeployRequest {
|
||||||
|
export const type = new RequestType<DeployParams, sqlops.DacFxResult, void, void>('dacfx/deploy');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------- < DacFx > ------------------------------------
|
||||||
@@ -8,7 +8,7 @@ import { SqlOpsDataClient, SqlOpsFeature } from 'dataprotocol-client';
|
|||||||
import { ClientCapabilities, StaticFeature, RPCMessageType, ServerCapabilities } from 'vscode-languageclient';
|
import { ClientCapabilities, StaticFeature, RPCMessageType, ServerCapabilities } from 'vscode-languageclient';
|
||||||
import { Disposable } from 'vscode';
|
import { Disposable } from 'vscode';
|
||||||
import { Telemetry } from './telemetry';
|
import { Telemetry } from './telemetry';
|
||||||
import * as contracts from './contracts';
|
import * as contracts from './contracts';
|
||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
import * as Utils from './utils';
|
import * as Utils from './utils';
|
||||||
import * as UUID from 'vscode-languageclient/lib/utils/uuid';
|
import * as UUID from 'vscode-languageclient/lib/utils/uuid';
|
||||||
@@ -28,6 +28,94 @@ export class TelemetryFeature implements StaticFeature {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class DacFxServicesFeature extends SqlOpsFeature<undefined> {
|
||||||
|
private static readonly messageTypes: RPCMessageType[] = [
|
||||||
|
contracts.ExportRequest.type,
|
||||||
|
contracts.ImportRequest.type,
|
||||||
|
contracts.ExtractRequest.type,
|
||||||
|
contracts.DeployRequest.type
|
||||||
|
];
|
||||||
|
|
||||||
|
constructor(client: SqlOpsDataClient) {
|
||||||
|
super(client, DacFxServicesFeature.messageTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public fillClientCapabilities(capabilities: ClientCapabilities): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
public initialize(capabilities: ServerCapabilities): void {
|
||||||
|
this.register(this.messages, {
|
||||||
|
id: UUID.generateUuid(),
|
||||||
|
registerOptions: undefined
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected registerProvider(options: undefined): Disposable {
|
||||||
|
const client = this._client;
|
||||||
|
let self = this;
|
||||||
|
|
||||||
|
let exportBacpac = (databaseName: string, packageFilePath: string, ownerUri: string, taskExecutionMode: sqlops.TaskExecutionMode): Thenable<sqlops.DacFxResult> => {
|
||||||
|
let params: contracts.ExportParams = { databaseName: databaseName, packageFilePath: packageFilePath, ownerUri: ownerUri, taskExecutionMode: taskExecutionMode };
|
||||||
|
return client.sendRequest(contracts.ExportRequest.type, params).then(
|
||||||
|
r => {
|
||||||
|
return r;
|
||||||
|
},
|
||||||
|
e => {
|
||||||
|
client.logFailedRequest(contracts.ExportRequest.type, e);
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
let importBacpac = (packageFilePath: string, databaseName: string, ownerUri: string, taskExecutionMode: sqlops.TaskExecutionMode): Thenable<sqlops.DacFxResult> => {
|
||||||
|
let params: contracts.ImportParams = { packageFilePath: packageFilePath, databaseName: databaseName, ownerUri: ownerUri, taskExecutionMode: taskExecutionMode };
|
||||||
|
return client.sendRequest(contracts.ImportRequest.type, params).then(
|
||||||
|
r => {
|
||||||
|
return r;
|
||||||
|
},
|
||||||
|
e => {
|
||||||
|
client.logFailedRequest(contracts.ImportRequest.type, e);
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
let extractDacpac = (databaseName: string, packageFilePath: string, applicationName: string, applicationVersion: string, ownerUri: string, taskExecutionMode: sqlops.TaskExecutionMode): Thenable<sqlops.DacFxResult> => {
|
||||||
|
let params: contracts.ExtractParams = { databaseName: databaseName, packageFilePath: packageFilePath, applicationName: applicationName, applicationVersion: applicationVersion, ownerUri: ownerUri, taskExecutionMode: taskExecutionMode };
|
||||||
|
return client.sendRequest(contracts.ExtractRequest.type, params).then(
|
||||||
|
r => {
|
||||||
|
return r;
|
||||||
|
},
|
||||||
|
e => {
|
||||||
|
client.logFailedRequest(contracts.ExtractRequest.type, e);
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
let deployDacpac = (packageFilePath: string, targetDatabaseName: string, upgradeExisting: boolean, ownerUri: string, taskExecutionMode: sqlops.TaskExecutionMode): Thenable<sqlops.DacFxResult> => {
|
||||||
|
let params: contracts.DeployParams = { packageFilePath: packageFilePath, databaseName: targetDatabaseName, upgradeExisting: upgradeExisting, ownerUri: ownerUri, taskExecutionMode: taskExecutionMode };
|
||||||
|
return client.sendRequest(contracts.DeployRequest.type, params).then(
|
||||||
|
r => {
|
||||||
|
return r;
|
||||||
|
},
|
||||||
|
e => {
|
||||||
|
client.logFailedRequest(contracts.DeployRequest.type, e);
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return sqlops.dataprotocol.registerDacFxServicesProvider({
|
||||||
|
providerId: client.providerId,
|
||||||
|
exportBacpac,
|
||||||
|
importBacpac,
|
||||||
|
extractDacpac,
|
||||||
|
deployDacpac
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class AgentServicesFeature extends SqlOpsFeature<undefined> {
|
export class AgentServicesFeature extends SqlOpsFeature<undefined> {
|
||||||
private static readonly messagesTypes: RPCMessageType[] = [
|
private static readonly messagesTypes: RPCMessageType[] = [
|
||||||
contracts.AgentJobsRequest.type,
|
contracts.AgentJobsRequest.type,
|
||||||
@@ -229,7 +317,7 @@ export class AgentServicesFeature extends SqlOpsFeature<undefined> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Alert management methods
|
// Alert management methods
|
||||||
let getAlerts = (ownerUri: string): Thenable<sqlops.AgentAlertsResult> => {
|
let getAlerts = (ownerUri: string): Thenable<sqlops.AgentAlertsResult> => {
|
||||||
let params: contracts.AgentAlertsParams = {
|
let params: contracts.AgentAlertsParams = {
|
||||||
ownerUri: ownerUri
|
ownerUri: ownerUri
|
||||||
};
|
};
|
||||||
@@ -299,7 +387,7 @@ export class AgentServicesFeature extends SqlOpsFeature<undefined> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Operator management methods
|
// Operator management methods
|
||||||
let getOperators = (ownerUri: string): Thenable<sqlops.AgentOperatorsResult> => {
|
let getOperators = (ownerUri: string): Thenable<sqlops.AgentOperatorsResult> => {
|
||||||
let params: contracts.AgentOperatorsParams = {
|
let params: contracts.AgentOperatorsParams = {
|
||||||
ownerUri: ownerUri
|
ownerUri: ownerUri
|
||||||
};
|
};
|
||||||
@@ -369,7 +457,7 @@ export class AgentServicesFeature extends SqlOpsFeature<undefined> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Proxy management methods
|
// Proxy management methods
|
||||||
let getProxies = (ownerUri: string): Thenable<sqlops.AgentProxiesResult> => {
|
let getProxies = (ownerUri: string): Thenable<sqlops.AgentProxiesResult> => {
|
||||||
let params: contracts.AgentProxiesParams = {
|
let params: contracts.AgentProxiesParams = {
|
||||||
ownerUri: ownerUri
|
ownerUri: ownerUri
|
||||||
};
|
};
|
||||||
@@ -439,7 +527,7 @@ export class AgentServicesFeature extends SqlOpsFeature<undefined> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Agent Credential Method
|
// Agent Credential Method
|
||||||
let getCredentials = (ownerUri: string): Thenable<sqlops.GetCredentialsResult> => {
|
let getCredentials = (ownerUri: string): Thenable<sqlops.GetCredentialsResult> => {
|
||||||
let params: contracts.GetCredentialsParams = {
|
let params: contracts.GetCredentialsParams = {
|
||||||
ownerUri: ownerUri
|
ownerUri: ownerUri
|
||||||
};
|
};
|
||||||
@@ -455,7 +543,7 @@ export class AgentServicesFeature extends SqlOpsFeature<undefined> {
|
|||||||
|
|
||||||
|
|
||||||
// Job Schedule management methods
|
// Job Schedule management methods
|
||||||
let getJobSchedules = (ownerUri: string): Thenable<sqlops.AgentJobSchedulesResult> => {
|
let getJobSchedules = (ownerUri: string): Thenable<sqlops.AgentJobSchedulesResult> => {
|
||||||
let params: contracts.AgentJobScheduleParams = {
|
let params: contracts.AgentJobScheduleParams = {
|
||||||
ownerUri: ownerUri
|
ownerUri: ownerUri
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { CredentialStore } from './credentialstore/credentialstore';
|
|||||||
import { AzureResourceProvider } from './resourceProvider/resourceProvider';
|
import { AzureResourceProvider } from './resourceProvider/resourceProvider';
|
||||||
import * as Utils from './utils';
|
import * as Utils from './utils';
|
||||||
import { Telemetry, LanguageClientErrorHandler } from './telemetry';
|
import { Telemetry, LanguageClientErrorHandler } from './telemetry';
|
||||||
import { TelemetryFeature, AgentServicesFeature } from './features';
|
import { TelemetryFeature, AgentServicesFeature, DacFxServicesFeature } from './features';
|
||||||
|
|
||||||
const baseConfig = require('./config.json');
|
const baseConfig = require('./config.json');
|
||||||
const outputChannel = vscode.window.createOutputChannel(Constants.serviceName);
|
const outputChannel = vscode.window.createOutputChannel(Constants.serviceName);
|
||||||
@@ -55,7 +55,8 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
// we only want to add new features
|
// we only want to add new features
|
||||||
...SqlOpsDataClient.defaultFeatures,
|
...SqlOpsDataClient.defaultFeatures,
|
||||||
TelemetryFeature,
|
TelemetryFeature,
|
||||||
AgentServicesFeature
|
AgentServicesFeature,
|
||||||
|
DacFxServicesFeature,
|
||||||
],
|
],
|
||||||
outputChannel: new CustomOutputChannel()
|
outputChannel: new CustomOutputChannel()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ buffer-alloc-unsafe@^1.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
|
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
|
||||||
integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
|
integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
|
||||||
|
|
||||||
buffer-alloc@^1.1.0:
|
buffer-alloc@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
|
resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
|
||||||
integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
|
integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
|
||||||
@@ -75,19 +75,26 @@ core-util-is@~1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||||
|
|
||||||
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.2.8":
|
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.2.10":
|
||||||
version "0.2.8"
|
version "0.2.10"
|
||||||
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/3ec3ec3fa63a8dae958c18a85b91fec74c50aec5"
|
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/4de3f7caf0eba54159911b977ddb4f5d7c0a9ca8"
|
||||||
dependencies:
|
dependencies:
|
||||||
vscode-languageclient "3.5.1"
|
vscode-languageclient "3.5.1"
|
||||||
|
|
||||||
debug@3.1.0, debug@^3.1.0:
|
debug@3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
||||||
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
|
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
|
||||||
dependencies:
|
dependencies:
|
||||||
ms "2.0.0"
|
ms "2.0.0"
|
||||||
|
|
||||||
|
debug@^3.1.0:
|
||||||
|
version "3.2.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
|
||||||
|
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
|
||||||
|
dependencies:
|
||||||
|
ms "^2.1.1"
|
||||||
|
|
||||||
decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1:
|
decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1"
|
resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1"
|
||||||
@@ -161,9 +168,9 @@ end-of-stream@^1.0.0:
|
|||||||
once "^1.4.0"
|
once "^1.4.0"
|
||||||
|
|
||||||
es6-promise@^4.0.3:
|
es6-promise@^4.0.3:
|
||||||
version "4.2.4"
|
version "4.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29"
|
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.5.tgz#da6d0d5692efb461e082c14817fe2427d8f5d054"
|
||||||
integrity sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==
|
integrity sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==
|
||||||
|
|
||||||
es6-promisify@^5.0.0:
|
es6-promisify@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
@@ -213,9 +220,9 @@ get-stream@^2.2.0:
|
|||||||
pinkie-promise "^2.0.0"
|
pinkie-promise "^2.0.0"
|
||||||
|
|
||||||
graceful-fs@^4.1.10:
|
graceful-fs@^4.1.10:
|
||||||
version "4.1.11"
|
version "4.1.15"
|
||||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
|
||||||
integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=
|
integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
|
||||||
|
|
||||||
"graceful-readlink@>= 1.0.0":
|
"graceful-readlink@>= 1.0.0":
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
@@ -287,6 +294,11 @@ ms@2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||||
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
|
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
|
||||||
|
|
||||||
|
ms@^2.1.1:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
|
||||||
|
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
|
||||||
|
|
||||||
object-assign@^4.0.1:
|
object-assign@^4.0.1:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||||
@@ -300,9 +312,9 @@ once@^1.4.0:
|
|||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
opener@^1.4.3:
|
opener@^1.4.3:
|
||||||
version "1.4.3"
|
version "1.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8"
|
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed"
|
||||||
integrity sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=
|
integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==
|
||||||
|
|
||||||
os-tmpdir@~1.0.2:
|
os-tmpdir@~1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
@@ -367,9 +379,9 @@ seek-bzip@^1.0.5:
|
|||||||
commander "~2.8.1"
|
commander "~2.8.1"
|
||||||
|
|
||||||
semver@^5.3.0:
|
semver@^5.3.0:
|
||||||
version "5.5.0"
|
version "5.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
|
||||||
integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==
|
integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
|
||||||
|
|
||||||
"service-downloader@github:anthonydresser/service-downloader#0.1.5":
|
"service-downloader@github:anthonydresser/service-downloader#0.1.5":
|
||||||
version "0.1.5"
|
version "0.1.5"
|
||||||
@@ -397,16 +409,16 @@ strip-dirs@^2.0.0:
|
|||||||
is-natural-number "^4.0.1"
|
is-natural-number "^4.0.1"
|
||||||
|
|
||||||
tar-stream@^1.5.2:
|
tar-stream@^1.5.2:
|
||||||
version "1.6.1"
|
version "1.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.1.tgz#f84ef1696269d6223ca48f6e1eeede3f7e81f395"
|
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555"
|
||||||
integrity sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==
|
integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==
|
||||||
dependencies:
|
dependencies:
|
||||||
bl "^1.0.0"
|
bl "^1.0.0"
|
||||||
buffer-alloc "^1.1.0"
|
buffer-alloc "^1.2.0"
|
||||||
end-of-stream "^1.0.0"
|
end-of-stream "^1.0.0"
|
||||||
fs-constants "^1.0.0"
|
fs-constants "^1.0.0"
|
||||||
readable-stream "^2.3.0"
|
readable-stream "^2.3.0"
|
||||||
to-buffer "^1.1.0"
|
to-buffer "^1.1.1"
|
||||||
xtend "^4.0.0"
|
xtend "^4.0.0"
|
||||||
|
|
||||||
through@^2.3.6:
|
through@^2.3.6:
|
||||||
@@ -421,15 +433,15 @@ tmp@^0.0.33:
|
|||||||
dependencies:
|
dependencies:
|
||||||
os-tmpdir "~1.0.2"
|
os-tmpdir "~1.0.2"
|
||||||
|
|
||||||
to-buffer@^1.1.0:
|
to-buffer@^1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
|
resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
|
||||||
integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==
|
integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==
|
||||||
|
|
||||||
unbzip2-stream@^1.0.9:
|
unbzip2-stream@^1.0.9:
|
||||||
version "1.2.5"
|
version "1.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz#73a033a567bbbde59654b193c44d48a7e4f43c47"
|
resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz#7854da51622a7e63624221196357803b552966a1"
|
||||||
integrity sha512-izD3jxT8xkzwtXRUZjtmRwKnZoeECrfZ8ra/ketwOcusbZEp4mjULMnJOCfTDZBgGQAAY1AJ/IgxcwkavcX9Og==
|
integrity sha512-fIZnvdjblYs7Cru/xC6tCPVhz7JkYcVQQkePwMLyQELzYTds2Xn8QefPVnvdVhhZqubxNA1cASXEH5wcK0Bucw==
|
||||||
dependencies:
|
dependencies:
|
||||||
buffer "^3.0.1"
|
buffer "^3.0.1"
|
||||||
through "^2.3.6"
|
through "^2.3.6"
|
||||||
|
|||||||
17
extensions/notebook/README.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Notebook extension for Azure Data Studio
|
||||||
|
|
||||||
|
Welcome to the Notebook extension for Azure Data Studio! This extension supports core notebook functionality including configuration settings, actions such as New / Open Notebook, and more.
|
||||||
|
|
||||||
|
## Code of Conduct
|
||||||
|
|
||||||
|
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||||
|
|
||||||
|
## Privacy Statement
|
||||||
|
|
||||||
|
The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.microsoft.com/en-us/privacystatement) describes the privacy statement of this software.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
|
||||||
|
Licensed under the [Source EULA](https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt).
|
||||||
71
extensions/notebook/package.json
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
{
|
||||||
|
"name": "notebook",
|
||||||
|
"displayName": "%displayName%",
|
||||||
|
"description": "%description%",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"publisher": "Microsoft",
|
||||||
|
"engines": {
|
||||||
|
"vscode": "*",
|
||||||
|
"sqlops": "*"
|
||||||
|
},
|
||||||
|
"main": "./out/extension",
|
||||||
|
"activationEvents": [
|
||||||
|
"*"
|
||||||
|
],
|
||||||
|
"contributes": {
|
||||||
|
"configuration": {
|
||||||
|
"type": "object",
|
||||||
|
"title": "%notebook.configuration.title%",
|
||||||
|
"properties": {
|
||||||
|
"notebook.enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true,
|
||||||
|
"description": "%notebook.enabled.description%"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commands": [
|
||||||
|
{
|
||||||
|
"command": "notebook.command.new",
|
||||||
|
"title": "%notebook.command.new%",
|
||||||
|
"icon": {
|
||||||
|
"dark": "resources/dark/new_notebook_inverse.svg",
|
||||||
|
"light": "resources/light/new_notebook.svg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "notebook.command.open",
|
||||||
|
"title": "%notebook.command.open%",
|
||||||
|
"icon": {
|
||||||
|
"dark": "resources/dark/open_notebook_inverse.svg",
|
||||||
|
"light": "resources/light/open_notebook.svg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"menus": {
|
||||||
|
"commandPalette": [
|
||||||
|
{
|
||||||
|
"command": "notebook.command.new",
|
||||||
|
"when": "config.notebook.enabled"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "notebook.command.open",
|
||||||
|
"when": "config.notebook.enabled"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"keybindings": [
|
||||||
|
{
|
||||||
|
"command": "notebook.command.new",
|
||||||
|
"key": "Ctrl+Shift+N",
|
||||||
|
"when": "config.notebook.enabled"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"vscode-nls": "^4.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "8.0.33"
|
||||||
|
}
|
||||||
|
}
|
||||||
8
extensions/notebook/package.nls.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"displayName": "Notebook Core Extensions",
|
||||||
|
"description": "Defines the Data-procotol based Notebook contribution and many Notebook commands and contributions.",
|
||||||
|
"notebook.configuration.title": "Notebook configuration",
|
||||||
|
"notebook.enabled.description": "Enable viewing notebook files using built-in notebook editor.",
|
||||||
|
"notebook.command.new": "New Notebook",
|
||||||
|
"notebook.command.open": "Open Notebook"
|
||||||
|
}
|
||||||
1
extensions/notebook/resources/dark/new_notebook_inverse.svg
Executable file
@@ -0,0 +1 @@
|
|||||||
|
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#fff;}.cls-2{fill:#388a34;}</style></defs><title>new_notebook_inverse</title><path class="cls-1" d="M11.87,1.24V.33H9.13A3.78,3.78,0,0,0,7.92.52a3.48,3.48,0,0,0-1.07.58A3.6,3.6,0,0,0,5.78.52,3.78,3.78,0,0,0,4.57.33H1.83v.91H0V13.1H9.67v-.91H7a4,4,0,0,1,.47-.39A2.39,2.39,0,0,1,8,11.52a2.2,2.2,0,0,1,.53-.18,2.93,2.93,0,0,1,.61-.06h2.74V2.15h.91V9h.91V1.24Zm-9.13,0H4.57a3,3,0,0,1,1,.17,2.58,2.58,0,0,1,.85.49v8.93a3.94,3.94,0,0,0-.88-.35,3.73,3.73,0,0,0-.94-.12H2.74Zm-1.82,11v-10h.91v9.13H4.57a2.93,2.93,0,0,1,.61.06,2.55,2.55,0,0,1,.53.18,2.68,2.68,0,0,1,.49.28,3.29,3.29,0,0,1,.46.39Zm8.21-1.83a3.73,3.73,0,0,0-.94.12,4.22,4.22,0,0,0-.89.35V1.9a2.74,2.74,0,0,1,.86-.49,2.91,2.91,0,0,1,1-.17H11v9.12ZM12.87,10v2.2h-2.2v.91h3V10Z"/><polygon class="cls-2" points="16 12.19 16 13.13 13.8 13.13 13.8 15.33 12.87 15.33 12.87 13.13 10.67 13.13 10.67 12.19 12.87 12.19 12.87 9.99 13.8 9.99 13.8 12.19 16 12.19"/><path class="cls-2" d="M13.8,12.19V10h-.93v2.2h-2.2v.94h2.2v2.2h.93v-2.2H16v-.94Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
1
extensions/notebook/resources/dark/open_notebook_inverse.svg
Executable file
@@ -0,0 +1 @@
|
|||||||
|
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#fff;}.cls-2{fill:#0095d7;}</style></defs><title>open_notebook_inverse</title><path class="cls-1" d="M12.55,4.21l-.08-.11h-.56l-.69.06a1.54,1.54,0,0,0-.23.29v8.69H9.18a3.32,3.32,0,0,0-.93.13,3.34,3.34,0,0,0-.87.34V4.76a2.88,2.88,0,0,1,.43-.31A5.58,5.58,0,0,1,8.29,3.3a2.63,2.63,0,0,0-.3.09A3.62,3.62,0,0,0,6.93,4a3.68,3.68,0,0,0-1.07-.57A3.58,3.58,0,0,0,4.67,3.2H2v.9H.15V15.85H13.72V5.48ZM2.86,4.1H4.67a2.61,2.61,0,0,1,1,.17,2.32,2.32,0,0,1,.86.49v8.85a3.27,3.27,0,0,0-.88-.34,3.22,3.22,0,0,0-.93-.13H2.86ZM1,15V5H2v9H4.67a3.94,3.94,0,0,1,.61.06,3.2,3.2,0,0,1,.52.18,4.19,4.19,0,0,1,.49.29,2.28,2.28,0,0,1,.45.39ZM12.8,15H7.11a2.7,2.7,0,0,1,.47-.39A2.83,2.83,0,0,1,8,14.28a3.42,3.42,0,0,1,.54-.18A3.81,3.81,0,0,1,9.18,14h2.73V5h.89Z"/><polygon class="cls-2" points="13.2 3.56 13.2 3.58 13.19 3.57 13.2 3.56"/><path class="cls-2" d="M13.19,3.57h0v0Z"/><polygon class="cls-2" points="13.2 3.56 13.2 3.58 13.19 3.57 13.2 3.56"/><polygon class="cls-2" points="14.21 1.65 14.19 1.65 14.19 1.63 14.21 1.65"/><path class="cls-2" d="M15.91,2.1,14.2,3.81l-.38.38-.62-.61v0l1-1H12.79a3.35,3.35,0,0,0-1.09.26h0a3.94,3.94,0,0,0-.86.52l-.24.21s0,0,0,0a3.3,3.3,0,0,0-.51.67,3.1,3.1,0,0,0-.26.47A3.41,3.41,0,0,0,9.5,6.11H8.6a4.68,4.68,0,0,1,.16-1.19A4.74,4.74,0,0,1,9,4.26a2.21,2.21,0,0,1,.2-.41,4.66,4.66,0,0,1,.36-.51c.1-.13.22-.26.34-.39a4.14,4.14,0,0,1,.66-.53,1.19,1.19,0,0,1,.23-.16,2.79,2.79,0,0,1,.34-.18l.31-.13.42-.14a4.32,4.32,0,0,1,1.19-.16h1.15l-1-1L13.82,0Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
1
extensions/notebook/resources/light/new_notebook.svg
Executable file
@@ -0,0 +1 @@
|
|||||||
|
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#388a34;}</style></defs><title>new_notebook</title><path d="M11.86,1.24V.33H9.13A3.78,3.78,0,0,0,7.91.52a3.48,3.48,0,0,0-1.07.58A3.6,3.6,0,0,0,5.78.52,3.78,3.78,0,0,0,4.57.33H1.83v.91H0V13.1H9.66v-.91H7a4,4,0,0,1,.47-.39A2.39,2.39,0,0,1,8,11.52a2.2,2.2,0,0,1,.53-.18,2.93,2.93,0,0,1,.61-.06h2.74V2.15h.91V9h.91V1.24Zm-9.13,0H4.57a3,3,0,0,1,1,.17,2.58,2.58,0,0,1,.85.49v8.93a3.94,3.94,0,0,0-.88-.35,3.73,3.73,0,0,0-.94-.12H2.73Zm-1.82,11v-10h.91v9.13H4.57a2.93,2.93,0,0,1,.61.06,2.55,2.55,0,0,1,.53.18,2.68,2.68,0,0,1,.49.28,3.29,3.29,0,0,1,.46.39Zm8.21-1.83a3.73,3.73,0,0,0-.94.12,4.22,4.22,0,0,0-.89.35V1.9a2.74,2.74,0,0,1,.86-.49,2.91,2.91,0,0,1,1-.17h1.82v9.12ZM12.86,10v2.2h-2.2v.91h3V10Z"/><polygon class="cls-1" points="15.99 12.19 15.99 13.13 13.79 13.13 13.79 15.33 12.87 15.33 12.87 13.13 10.66 13.13 10.66 12.19 12.87 12.19 12.87 9.99 13.79 9.99 13.79 12.19 15.99 12.19"/><path class="cls-1" d="M13.79,12.19V10h-.93v2.2h-2.2v.94h2.2v2.2h.93v-2.2H16v-.94Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
1
extensions/notebook/resources/light/open_notebook.svg
Executable file
@@ -0,0 +1 @@
|
|||||||
|
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#00539c;}</style></defs><title>open_notebook</title><path d="M12.4,4.21l-.08-.11h-.56l-.69.06a1.54,1.54,0,0,0-.23.29v8.69H9a3.32,3.32,0,0,0-.93.13,3.34,3.34,0,0,0-.87.34V4.76a2.88,2.88,0,0,1,.43-.31A5.58,5.58,0,0,1,8.14,3.3a2.63,2.63,0,0,0-.3.09A3.62,3.62,0,0,0,6.78,4a3.68,3.68,0,0,0-1.07-.57A3.58,3.58,0,0,0,4.52,3.2H1.81v.9H0V15.85H13.57V5.48ZM2.71,4.1H4.52a2.61,2.61,0,0,1,1,.17,2.32,2.32,0,0,1,.86.49v8.85a3.27,3.27,0,0,0-.88-.34,3.22,3.22,0,0,0-.93-.13H2.71ZM.9,15V5h.91v9H4.52a3.94,3.94,0,0,1,.61.06,3.2,3.2,0,0,1,.52.18,4.19,4.19,0,0,1,.49.29,2.28,2.28,0,0,1,.45.39Zm11.75,0H7a2.7,2.7,0,0,1,.47-.39,2.83,2.83,0,0,1,.47-.29,3.42,3.42,0,0,1,.54-.18A3.81,3.81,0,0,1,9,14h2.73V5h.89Z"/><polygon class="cls-1" points="13.05 3.56 13.05 3.58 13.04 3.57 13.05 3.56"/><path class="cls-1" d="M13,3.57h0v0Z"/><polygon class="cls-1" points="13.05 3.56 13.05 3.58 13.04 3.57 13.05 3.56"/><polygon class="cls-1" points="14.06 1.65 14.04 1.65 14.04 1.63 14.06 1.65"/><path class="cls-1" d="M15.76,2.1,14,3.81l-.38.38L13,3.58v0l1-1H12.64a3.35,3.35,0,0,0-1.09.26h0a3.94,3.94,0,0,0-.86.52l-.24.21s0,0,0,0a3.3,3.3,0,0,0-.51.67,3.1,3.1,0,0,0-.26.47,3.41,3.41,0,0,0-.27,1.39h-.9a4.68,4.68,0,0,1,.16-1.19,4.74,4.74,0,0,1,.25-.66,2.21,2.21,0,0,1,.2-.41,4.66,4.66,0,0,1,.36-.51c.1-.13.22-.26.34-.39a4.14,4.14,0,0,1,.66-.53,1.19,1.19,0,0,1,.23-.16A2.79,2.79,0,0,1,11,2.08l.31-.13.42-.14a4.32,4.32,0,0,1,1.19-.16h1.15l-1-1L13.67,0Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
50
extensions/notebook/src/extension.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 * as vscode from 'vscode';
|
||||||
|
import * as sqlops from 'sqlops';
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
|
let counter = 0;
|
||||||
|
|
||||||
|
export function activate(extensionContext: vscode.ExtensionContext) {
|
||||||
|
extensionContext.subscriptions.push(vscode.commands.registerCommand('notebook.command.new', () => {
|
||||||
|
let title = `Untitled-${counter++}`;
|
||||||
|
let untitledUri = vscode.Uri.parse(`untitled:${title}`);
|
||||||
|
sqlops.nb.showNotebookDocument(untitledUri).then(success => {
|
||||||
|
|
||||||
|
}, (err: Error) => {
|
||||||
|
vscode.window.showErrorMessage(err.message);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
extensionContext.subscriptions.push(vscode.commands.registerCommand('notebook.command.open', () => {
|
||||||
|
openNotebook();
|
||||||
|
}));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openNotebook(): Promise<void> {
|
||||||
|
try {
|
||||||
|
let filter = {};
|
||||||
|
// TODO support querying valid notebook file types
|
||||||
|
filter[localize('notebookFiles', 'Notebooks')] = ['ipynb'];
|
||||||
|
let file = await vscode.window.showOpenDialog({
|
||||||
|
filters: filter
|
||||||
|
});
|
||||||
|
if (file) {
|
||||||
|
let doc = await vscode.workspace.openTextDocument(file[0]);
|
||||||
|
vscode.window.showTextDocument(doc);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
vscode.window.showErrorMessage(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this method is called when your extension is deactivated
|
||||||
|
export function deactivate() {
|
||||||
|
}
|
||||||
9
extensions/notebook/src/typings/refs.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/// <reference path='../../../../src/sql/sqlops.d.ts'/>
|
||||||
|
/// <reference path='../../../../src/sql/sqlops.proposed.d.ts'/>
|
||||||
|
/// <reference path='../../../../src/vs/vscode.d.ts'/>
|
||||||
|
/// <reference types='@types/node'/>
|
||||||
22
extensions/notebook/tsconfig.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"compileOnSave": true,
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "commonjs",
|
||||||
|
"target": "es6",
|
||||||
|
"outDir": "./out",
|
||||||
|
"lib": [
|
||||||
|
"es6", "es2015.promise"
|
||||||
|
],
|
||||||
|
"typeRoots": [
|
||||||
|
"./node_modules/@types"
|
||||||
|
],
|
||||||
|
"sourceMap": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"declaration": true
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
|
}
|
||||||
13
extensions/notebook/yarn.lock
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
"@types/node@8.0.33":
|
||||||
|
version "8.0.33"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.33.tgz#1126e94374014e54478092830704f6ea89df04cd"
|
||||||
|
integrity sha512-vmCdO8Bm1ExT+FWfC9sd9r4jwqM7o97gGy2WBshkkXbf/2nLAJQUrZfIhw27yVOtLUev6kSZc4cav/46KbDd8A==
|
||||||
|
|
||||||
|
vscode-nls@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002"
|
||||||
|
integrity sha512-qCfdzcH+0LgQnBpZA53bA32kzp9rpq/f66Som577ObeuDlFIrtbEJ+A/+CCxjIh4G8dpJYNCKIsxpRAHIfsbNw==
|
||||||
@@ -12,13 +12,10 @@ import { CreateSessionData } from '../data/createSessionData';
|
|||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
export class CreateSessionDialog {
|
export class CreateSessionDialog {
|
||||||
private readonly _providerType: string;
|
|
||||||
|
|
||||||
// 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', 'Start');
|
||||||
private readonly DialogTitleText: string = localize('createSessionDialog.title', 'Create New Profiler Session');
|
private readonly DialogTitleText: string = localize('createSessionDialog.title', 'Start New Profiler Session');
|
||||||
|
|
||||||
// UI Components
|
// UI Components
|
||||||
private dialog: sqlops.window.modelviewdialog.Dialog;
|
private dialog: sqlops.window.modelviewdialog.Dialog;
|
||||||
@@ -26,6 +23,7 @@ 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;
|
||||||
@@ -46,7 +44,7 @@ export class CreateSessionDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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(() => { });
|
||||||
@@ -70,6 +68,10 @@ export class CreateSessionDialog {
|
|||||||
value: ''
|
value: ''
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
|
this.templatesBox.onValueChanged(() => {
|
||||||
|
this.updateSessionName();
|
||||||
|
});
|
||||||
|
|
||||||
let formModel = view.modelBuilder.formContainer()
|
let formModel = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
components: [{
|
components: [{
|
||||||
@@ -81,13 +83,14 @@ 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);
|
||||||
|
|
||||||
if (this.model.templates) {
|
if (this.model.templates) {
|
||||||
this.templatesBox.values = this.model.getTemplateNames();
|
this.templatesBox.values = this.model.getTemplateNames();
|
||||||
|
this.updateSessionName();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sessionNameBox.onTextChanged(() => {
|
this.sessionNameBox.onTextChanged(() => {
|
||||||
@@ -101,6 +104,12 @@ export class CreateSessionDialog {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private updateSessionName() {
|
||||||
|
if (this.templatesBox.value) {
|
||||||
|
this.sessionNameBox.value = `ADS_${this.templatesBox.value.toString()}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async execute(): Promise<void> {
|
private async execute(): Promise<void> {
|
||||||
let profilerService = sqlops.dataprotocol.getProvider<sqlops.ProfilerProvider>(this._providerType, sqlops.DataProviderType.ProfilerProvider);
|
let profilerService = sqlops.dataprotocol.getProvider<sqlops.ProfilerProvider>(this._providerType, sqlops.DataProviderType.ProfilerProvider);
|
||||||
|
|
||||||
|
|||||||
@@ -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.3.0",
|
"version": "0.6.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,10 +26,9 @@
|
|||||||
"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,13 +48,23 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"menus": {
|
"menus": {
|
||||||
"objectExplorer/item/context": [
|
"commandPalette": [{
|
||||||
|
"command": "profiler.start",
|
||||||
|
"when": "False"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"command": "profiler.newProfiler",
|
"command": "profiler.stop",
|
||||||
"when": "connectionProvider == MSSQL && nodeType && nodeType == Server",
|
"when": "False"
|
||||||
"group": "profiler"
|
}, {
|
||||||
|
"command": "profiler.openCreateSessionDialog",
|
||||||
|
"when": "False"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"objectExplorer/item/context": [{
|
||||||
|
"command": "profiler.newProfiler",
|
||||||
|
"when": "connectionProvider == MSSQL && nodeType && nodeType == Server",
|
||||||
|
"group": "profiler"
|
||||||
|
}]
|
||||||
},
|
},
|
||||||
"outputChannels": [
|
"outputChannels": [
|
||||||
"sqlprofiler"
|
"sqlprofiler"
|
||||||
|
|||||||
24
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "azuredatastudio",
|
"name": "azuredatastudio",
|
||||||
"version": "1.2.4",
|
"version": "1.3.7",
|
||||||
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
|
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Microsoft Corporation"
|
"name": "Microsoft Corporation"
|
||||||
@@ -37,8 +37,10 @@
|
|||||||
"@angular/router": "~4.1.3",
|
"@angular/router": "~4.1.3",
|
||||||
"@angular/upgrade": "~4.1.3",
|
"@angular/upgrade": "~4.1.3",
|
||||||
"@types/chart.js": "^2.7.31",
|
"@types/chart.js": "^2.7.31",
|
||||||
|
"@types/htmlparser2": "^3.7.31",
|
||||||
"angular2-grid": "2.0.6",
|
"angular2-grid": "2.0.6",
|
||||||
"angular2-slickgrid": "github:Microsoft/angular2-slickgrid#1.4.6",
|
"angular2-slickgrid": "github:Microsoft/angular2-slickgrid#1.4.6",
|
||||||
|
"ansi_up": "^3.0.0",
|
||||||
"applicationinsights": "0.18.0",
|
"applicationinsights": "0.18.0",
|
||||||
"chart.js": "^2.6.0",
|
"chart.js": "^2.6.0",
|
||||||
"fast-plist": "0.1.2",
|
"fast-plist": "0.1.2",
|
||||||
@@ -64,8 +66,9 @@
|
|||||||
"pretty-data": "^0.40.0",
|
"pretty-data": "^0.40.0",
|
||||||
"reflect-metadata": "^0.1.8",
|
"reflect-metadata": "^0.1.8",
|
||||||
"rxjs": "5.4.0",
|
"rxjs": "5.4.0",
|
||||||
|
"sanitize-html": "^1.19.1",
|
||||||
"semver": "^5.5.0",
|
"semver": "^5.5.0",
|
||||||
"slickgrid": "github:anthonydresser/SlickGrid#2.3.28",
|
"slickgrid": "github:anthonydresser/SlickGrid#2.3.29",
|
||||||
"spdlog": "0.7.1",
|
"spdlog": "0.7.1",
|
||||||
"sudo-prompt": "8.2.0",
|
"sudo-prompt": "8.2.0",
|
||||||
"svg.js": "^2.2.5",
|
"svg.js": "^2.2.5",
|
||||||
@@ -85,7 +88,9 @@
|
|||||||
"@types/keytar": "4.0.1",
|
"@types/keytar": "4.0.1",
|
||||||
"@types/minimist": "1.2.0",
|
"@types/minimist": "1.2.0",
|
||||||
"@types/mocha": "2.2.39",
|
"@types/mocha": "2.2.39",
|
||||||
|
"@types/sanitize-html": "^1.18.2",
|
||||||
"@types/semver": "5.3.30",
|
"@types/semver": "5.3.30",
|
||||||
|
"@types/should": "^13.0.0",
|
||||||
"@types/sinon": "1.16.34",
|
"@types/sinon": "1.16.34",
|
||||||
"@types/winreg": "^1.2.30",
|
"@types/winreg": "^1.2.30",
|
||||||
"asar": "^0.14.0",
|
"asar": "^0.14.0",
|
||||||
@@ -98,12 +103,12 @@
|
|||||||
"documentdb": "^1.5.1",
|
"documentdb": "^1.5.1",
|
||||||
"electron-mksnapshot": "~1.7.0",
|
"electron-mksnapshot": "~1.7.0",
|
||||||
"eslint": "^3.4.0",
|
"eslint": "^3.4.0",
|
||||||
"event-stream": "^3.1.7",
|
"event-stream": "3.3.4",
|
||||||
"express": "^4.13.1",
|
"express": "^4.13.1",
|
||||||
"glob": "^5.0.13",
|
"glob": "^5.0.13",
|
||||||
"gulp": "^3.9.1",
|
"gulp": "^3.9.1",
|
||||||
"gulp-atom-electron": "^1.16.1",
|
"gulp-atom-electron": "^1.19.2",
|
||||||
"gulp-azure-storage": "^0.7.0",
|
"gulp-azure-storage": "^0.8.2",
|
||||||
"gulp-bom": "^1.0.0",
|
"gulp-bom": "^1.0.0",
|
||||||
"gulp-buffer": "0.0.2",
|
"gulp-buffer": "0.0.2",
|
||||||
"gulp-cli": "^2.0.1",
|
"gulp-cli": "^2.0.1",
|
||||||
@@ -116,7 +121,7 @@
|
|||||||
"gulp-json-editor": "^2.2.1",
|
"gulp-json-editor": "^2.2.1",
|
||||||
"gulp-mocha": "^2.1.3",
|
"gulp-mocha": "^2.1.3",
|
||||||
"gulp-plumber": "^1.2.0",
|
"gulp-plumber": "^1.2.0",
|
||||||
"gulp-remote-src": "^0.4.0",
|
"gulp-remote-src": "^0.4.4",
|
||||||
"gulp-rename": "^1.2.0",
|
"gulp-rename": "^1.2.0",
|
||||||
"gulp-replace": "^0.5.4",
|
"gulp-replace": "^0.5.4",
|
||||||
"gulp-shell": "^0.5.2",
|
"gulp-shell": "^0.5.2",
|
||||||
@@ -125,7 +130,7 @@
|
|||||||
"gulp-tslint": "^8.1.2",
|
"gulp-tslint": "^8.1.2",
|
||||||
"gulp-uglify": "^3.0.0",
|
"gulp-uglify": "^3.0.0",
|
||||||
"gulp-util": "^3.0.6",
|
"gulp-util": "^3.0.6",
|
||||||
"gulp-vinyl-zip": "^1.2.2",
|
"gulp-vinyl-zip": "^2.1.2",
|
||||||
"husky": "^0.13.1",
|
"husky": "^0.13.1",
|
||||||
"innosetup-compiler": "^5.5.60",
|
"innosetup-compiler": "^5.5.60",
|
||||||
"is": "^3.1.0",
|
"is": "^3.1.0",
|
||||||
@@ -144,8 +149,10 @@
|
|||||||
"queue": "3.0.6",
|
"queue": "3.0.6",
|
||||||
"remap-istanbul": "^0.6.4",
|
"remap-istanbul": "^0.6.4",
|
||||||
"rimraf": "^2.2.8",
|
"rimraf": "^2.2.8",
|
||||||
|
"should": "^13.2.3",
|
||||||
"sinon": "^1.17.2",
|
"sinon": "^1.17.2",
|
||||||
"source-map": "^0.4.4",
|
"source-map": "^0.4.4",
|
||||||
|
"temp-write": "^3.4.0",
|
||||||
"tslint": "^5.9.1",
|
"tslint": "^5.9.1",
|
||||||
"typemoq": "^0.3.2",
|
"typemoq": "^0.3.2",
|
||||||
"typescript": "2.9.2",
|
"typescript": "2.9.2",
|
||||||
@@ -170,6 +177,7 @@
|
|||||||
"windows-process-tree": "0.2.2"
|
"windows-process-tree": "0.2.2"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"rc": "1.2.8"
|
"rc": "1.2.8",
|
||||||
|
"event-stream": "3.3.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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 "$@"
|
||||||
|
|||||||
@@ -12,9 +12,10 @@ import * as types from 'vs/base/common/types';
|
|||||||
|
|
||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
|
|
||||||
export function appendRow(container: Builder, label: string, labelClass: string, cellContainerClass: string): Builder {
|
export function appendRow(container: Builder, label: string, labelClass: string, cellContainerClass: string, rowContainerClass?: string): Builder {
|
||||||
let cellContainer: Builder;
|
let cellContainer: Builder;
|
||||||
container.element('tr', {}, (rowContainer) => {
|
let rowAttributes = rowContainerClass ? { class: rowContainerClass } : {};
|
||||||
|
container.element('tr', rowAttributes, (rowContainer) => {
|
||||||
rowContainer.element('td', { class: labelClass }, (labelCellContainer) => {
|
rowContainer.element('td', { class: labelClass }, (labelCellContainer) => {
|
||||||
labelCellContainer.div({}, (labelContainer) => {
|
labelCellContainer.div({}, (labelContainer) => {
|
||||||
labelContainer.text(label);
|
labelContainer.text(label);
|
||||||
|
|||||||
@@ -236,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -28,8 +28,11 @@ export class RadioButton extends Widget {
|
|||||||
super();
|
super();
|
||||||
this.inputElement = document.createElement('input');
|
this.inputElement = document.createElement('input');
|
||||||
this.inputElement.type = 'radio';
|
this.inputElement.type = 'radio';
|
||||||
|
this.inputElement.style.verticalAlign = 'middle';
|
||||||
|
this.inputElement.style.margin = '3px';
|
||||||
|
|
||||||
this._label = document.createElement('span');
|
this._label = document.createElement('span');
|
||||||
|
this._label.style.verticalAlign = 'middle';
|
||||||
|
|
||||||
this.label = opts.label;
|
this.label = opts.label;
|
||||||
this.enabled = opts.enabled || true;
|
this.enabled = opts.enabled || true;
|
||||||
|
|||||||
10
src/sql/base/browser/ui/selectBox/media/selectBox.css
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
.labelOnTopContainer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.labelOnLeftContainer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
@@ -4,6 +4,8 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
import 'vs/css!./media/selectBox';
|
||||||
|
|
||||||
import { SelectBox as vsSelectBox, ISelectBoxStyles as vsISelectBoxStyles, ISelectBoxOptions } from 'vs/base/browser/ui/selectBox/selectBox';
|
import { SelectBox as vsSelectBox, ISelectBoxStyles as vsISelectBoxStyles, ISelectBoxOptions } from 'vs/base/browser/ui/selectBox/selectBox';
|
||||||
import { Color } from 'vs/base/common/color';
|
import { Color } from 'vs/base/common/color';
|
||||||
import { IContextViewProvider, AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
|
import { IContextViewProvider, AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
|
||||||
@@ -30,6 +32,7 @@ export class SelectBox extends vsSelectBox {
|
|||||||
private _optionsDictionary;
|
private _optionsDictionary;
|
||||||
private _dialogOptions: string[];
|
private _dialogOptions: string[];
|
||||||
private _selectedOption: string;
|
private _selectedOption: string;
|
||||||
|
private _selectBoxOptions: ISelectBoxOptions;
|
||||||
private enabledSelectBackground: Color;
|
private enabledSelectBackground: Color;
|
||||||
private enabledSelectForeground: Color;
|
private enabledSelectForeground: Color;
|
||||||
private enabledSelectBorder: Color;
|
private enabledSelectBorder: Color;
|
||||||
@@ -72,6 +75,12 @@ export class SelectBox extends vsSelectBox {
|
|||||||
|
|
||||||
// explicitly set the accessible role so that the screen readers can read the control type properly
|
// explicitly set the accessible role so that the screen readers can read the control type properly
|
||||||
this.selectElement.setAttribute('role', 'combobox');
|
this.selectElement.setAttribute('role', 'combobox');
|
||||||
|
|
||||||
|
this._selectBoxOptions = selectBoxOptions;
|
||||||
|
var focusTracker = dom.trackFocus(this.selectElement);
|
||||||
|
this._register(focusTracker);
|
||||||
|
this._register(focusTracker.onDidBlur(() => this._hideMessage()));
|
||||||
|
this._register(focusTracker.onDidFocus(() => this._showMessage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public style(styles: ISelectBoxStyles): void {
|
public style(styles: ISelectBoxStyles): void {
|
||||||
@@ -118,6 +127,10 @@ export class SelectBox extends vsSelectBox {
|
|||||||
return this._selectedOption;
|
return this._selectedOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get values(): string[] {
|
||||||
|
return this._dialogOptions;
|
||||||
|
}
|
||||||
|
|
||||||
public enable(): void {
|
public enable(): void {
|
||||||
this.selectElement.disabled = false;
|
this.selectElement.disabled = false;
|
||||||
this.selectBackground = this.enabledSelectBackground;
|
this.selectBackground = this.enabledSelectBackground;
|
||||||
@@ -134,6 +147,10 @@ export class SelectBox extends vsSelectBox {
|
|||||||
this.applyStyles();
|
this.applyStyles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public hasFocus(): boolean {
|
||||||
|
return document.activeElement === this.selectElement;
|
||||||
|
}
|
||||||
|
|
||||||
public showMessage(message: IMessage): void {
|
public showMessage(message: IMessage): void {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
|
|
||||||
@@ -155,7 +172,9 @@ export class SelectBox extends vsSelectBox {
|
|||||||
|
|
||||||
aria.alert(alertText);
|
aria.alert(alertText);
|
||||||
|
|
||||||
this._showMessage();
|
if (this.hasFocus()) {
|
||||||
|
this._showMessage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public _showMessage(): void {
|
public _showMessage(): void {
|
||||||
@@ -226,4 +245,34 @@ export class SelectBox extends vsSelectBox {
|
|||||||
default: return { border: this.inputValidationErrorBorder, background: this.inputValidationErrorBackground };
|
default: return { border: this.inputValidationErrorBorder, background: this.inputValidationErrorBackground };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public render(container: HTMLElement): void {
|
||||||
|
let selectOptions: ISelectBoxOptionsWithLabel = this._selectBoxOptions as ISelectBoxOptionsWithLabel;
|
||||||
|
|
||||||
|
if (selectOptions && selectOptions.labelText && selectOptions.labelText !== undefined) {
|
||||||
|
let outerContainer = document.createElement('div');
|
||||||
|
let selectContainer = document.createElement('div');
|
||||||
|
|
||||||
|
outerContainer.className = selectOptions.labelOnTop ? 'labelOnTopContainer' : 'labelOnLeftContainer';
|
||||||
|
|
||||||
|
let labelText = document.createElement('div');
|
||||||
|
labelText.className = 'action-item-label';
|
||||||
|
labelText.innerHTML = selectOptions.labelText;
|
||||||
|
|
||||||
|
container.appendChild(outerContainer);
|
||||||
|
outerContainer.appendChild(labelText);
|
||||||
|
outerContainer.appendChild(selectContainer);
|
||||||
|
|
||||||
|
super.render(selectContainer);
|
||||||
|
this.selectElement.classList.add('action-item-label');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
super.render(container);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ISelectBoxOptionsWithLabel extends ISelectBoxOptions {
|
||||||
|
labelText?: string;
|
||||||
|
labelOnTop?: boolean;
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,36 +9,27 @@ 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: (startIndex: number, count: number) => void): void;
|
||||||
|
setLength(number): void;
|
||||||
dispose(): void;
|
dispose(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IGridDataRow {
|
|
||||||
row?: number;
|
|
||||||
values: any[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum CollectionChange {
|
|
||||||
ItemsReplaced
|
|
||||||
}
|
|
||||||
|
|
||||||
class LoadCancellationToken {
|
class LoadCancellationToken {
|
||||||
isCancelled: boolean;
|
isCancelled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DataWindow<TData> {
|
class DataWindow<T> {
|
||||||
private _data: TData[];
|
private _data: T[];
|
||||||
private _length: number = 0;
|
private _length: number = 0;
|
||||||
private _offsetFromDataSource: number = -1;
|
private _offsetFromDataSource: number = -1;
|
||||||
|
|
||||||
private lastLoadCancellationToken: LoadCancellationToken;
|
private lastLoadCancellationToken: LoadCancellationToken;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private loadFunction: (offset: number, count: number) => Thenable<TData[]>,
|
private loadFunction: (offset: number, count: number) => Thenable<T[]>,
|
||||||
private placeholderItemGenerator: (index: number) => TData,
|
private placeholderItemGenerator: (index: number) => T,
|
||||||
private loadCompleteCallback: (start: number, end: number) => void
|
private loadCompleteCallback: (start: number, end: number) => void
|
||||||
) {
|
) { }
|
||||||
}
|
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
this._data = undefined;
|
this._data = undefined;
|
||||||
@@ -50,26 +41,26 @@ class DataWindow<TData> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getStartIndex(): number {
|
public getStartIndex(): number {
|
||||||
return this._offsetFromDataSource;
|
return this._offsetFromDataSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
getEndIndex(): number {
|
public getEndIndex(): number {
|
||||||
return this._offsetFromDataSource + this._length;
|
return this._offsetFromDataSource + this._length;
|
||||||
}
|
}
|
||||||
|
|
||||||
contains(dataSourceIndex: number): boolean {
|
public contains(dataSourceIndex: number): boolean {
|
||||||
return dataSourceIndex >= this.getStartIndex() && dataSourceIndex < this.getEndIndex();
|
return dataSourceIndex >= this.getStartIndex() && dataSourceIndex < this.getEndIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
getItem(index: number): TData {
|
public getItem(index: number): T {
|
||||||
if (!this._data) {
|
if (!this._data) {
|
||||||
return this.placeholderItemGenerator(index);
|
return this.placeholderItemGenerator(index);
|
||||||
}
|
}
|
||||||
return this._data[index - this._offsetFromDataSource];
|
return this._data[index - this._offsetFromDataSource];
|
||||||
}
|
}
|
||||||
|
|
||||||
positionWindow(offset: number, length: number): void {
|
public positionWindow(offset: number, length: number): void {
|
||||||
this._offsetFromDataSource = offset;
|
this._offsetFromDataSource = offset;
|
||||||
this._length = length;
|
this._length = length;
|
||||||
this._data = undefined;
|
this._data = undefined;
|
||||||
@@ -92,34 +83,28 @@ class DataWindow<TData> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class VirtualizedCollection<TData> implements IObservableCollection<TData> {
|
export class VirtualizedCollection<T extends Slick.SlickData> implements IObservableCollection<T> {
|
||||||
|
private _bufferWindowBefore: DataWindow<T>;
|
||||||
|
private _window: DataWindow<T>;
|
||||||
|
private _bufferWindowAfter: DataWindow<T>;
|
||||||
|
|
||||||
private _length: number;
|
private collectionChangedCallback: (startIndex: number, count: number) => void;
|
||||||
private _windowSize: number;
|
|
||||||
private _bufferWindowBefore: DataWindow<TData>;
|
|
||||||
private _window: DataWindow<TData>;
|
|
||||||
private _bufferWindowAfter: DataWindow<TData>;
|
|
||||||
|
|
||||||
private collectionChangedCallback: (change: CollectionChange, startIndex: number, count: number) => void;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
windowSize: number,
|
private readonly windowSize: number,
|
||||||
length: number,
|
private placeHolderGenerator: (index: number) => T,
|
||||||
loadFn: (offset: number, count: number) => Thenable<TData[]>,
|
private length: number,
|
||||||
private _placeHolderGenerator: (index: number) => TData
|
loadFn: (offset: number, count: number) => Thenable<T[]>
|
||||||
) {
|
) {
|
||||||
this._windowSize = windowSize;
|
|
||||||
this._length = length;
|
|
||||||
|
|
||||||
let loadCompleteCallback = (start: number, end: number) => {
|
let loadCompleteCallback = (start: number, end: number) => {
|
||||||
if (this.collectionChangedCallback) {
|
if (this.collectionChangedCallback) {
|
||||||
this.collectionChangedCallback(CollectionChange.ItemsReplaced, start, end - start);
|
this.collectionChangedCallback(start, end - start);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this._bufferWindowBefore = new DataWindow(loadFn, _placeHolderGenerator, loadCompleteCallback);
|
this._bufferWindowBefore = new DataWindow(loadFn, placeHolderGenerator, loadCompleteCallback);
|
||||||
this._window = new DataWindow(loadFn, _placeHolderGenerator, loadCompleteCallback);
|
this._window = new DataWindow(loadFn, placeHolderGenerator, loadCompleteCallback);
|
||||||
this._bufferWindowAfter = new DataWindow(loadFn, _placeHolderGenerator, loadCompleteCallback);
|
this._bufferWindowAfter = new DataWindow(loadFn, placeHolderGenerator, loadCompleteCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
@@ -128,19 +113,23 @@ export class VirtualizedCollection<TData> implements IObservableCollection<TData
|
|||||||
this._window.dispose();
|
this._window.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
setCollectionChangedCallback(callback: (change: CollectionChange, startIndex: number, count: number) => void): void {
|
public setCollectionChangedCallback(callback: (startIndex: number, count: number) => void): void {
|
||||||
this.collectionChangedCallback = callback;
|
this.collectionChangedCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
getLength(): number {
|
public getLength(): number {
|
||||||
return this._length;
|
return this.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
at(index: number): TData {
|
setLength(number: any): void {
|
||||||
|
this.length = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public at(index: number): T {
|
||||||
return this.getRange(index, index + 1)[0];
|
return this.getRange(index, index + 1)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
getRange(start: number, end: number): TData[] {
|
public getRange(start: number, end: number): T[] {
|
||||||
|
|
||||||
// current data may contain placeholders
|
// current data may contain placeholders
|
||||||
let currentData = this.getRangeFromCurrent(start, end);
|
let currentData = this.getRangeFromCurrent(start, end);
|
||||||
@@ -155,7 +144,7 @@ export class VirtualizedCollection<TData> implements IObservableCollection<TData
|
|||||||
this._bufferWindowAfter = this._window;
|
this._bufferWindowAfter = this._window;
|
||||||
this._window = this._bufferWindowBefore;
|
this._window = this._bufferWindowBefore;
|
||||||
this._bufferWindowBefore = windowToRecycle;
|
this._bufferWindowBefore = windowToRecycle;
|
||||||
let newWindowOffset = Math.max(0, this._window.getStartIndex() - this._windowSize);
|
let newWindowOffset = Math.max(0, this._window.getStartIndex() - this.windowSize);
|
||||||
|
|
||||||
this._bufferWindowBefore.positionWindow(newWindowOffset, this._window.getStartIndex() - newWindowOffset);
|
this._bufferWindowBefore.positionWindow(newWindowOffset, this._window.getStartIndex() - newWindowOffset);
|
||||||
} else if (start >= this._bufferWindowAfter.getStartIndex()) {
|
} else if (start >= this._bufferWindowAfter.getStartIndex()) {
|
||||||
@@ -164,8 +153,8 @@ export class VirtualizedCollection<TData> implements IObservableCollection<TData
|
|||||||
this._bufferWindowBefore = this._window;
|
this._bufferWindowBefore = this._window;
|
||||||
this._window = this._bufferWindowAfter;
|
this._window = this._bufferWindowAfter;
|
||||||
this._bufferWindowAfter = windowToRecycle;
|
this._bufferWindowAfter = windowToRecycle;
|
||||||
let newWindowOffset = Math.min(this._window.getStartIndex() + this._windowSize, this._length);
|
let newWindowOffset = Math.min(this._window.getStartIndex() + this.windowSize, this.length);
|
||||||
let newWindowLength = Math.min(this._length - newWindowOffset, this._windowSize);
|
let newWindowLength = Math.min(this.length - newWindowOffset, this.windowSize);
|
||||||
|
|
||||||
this._bufferWindowAfter.positionWindow(newWindowOffset, newWindowLength);
|
this._bufferWindowAfter.positionWindow(newWindowOffset, newWindowLength);
|
||||||
}
|
}
|
||||||
@@ -173,7 +162,7 @@ export class VirtualizedCollection<TData> implements IObservableCollection<TData
|
|||||||
return currentData;
|
return currentData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getRangeFromCurrent(start: number, end: number): TData[] {
|
private getRangeFromCurrent(start: number, end: number): T[] {
|
||||||
let currentData = [];
|
let currentData = [];
|
||||||
for (let i = 0; i < end - start; i++) {
|
for (let i = 0; i < end - start; i++) {
|
||||||
currentData.push(this.getDataFromCurrent(start + i));
|
currentData.push(this.getDataFromCurrent(start + i));
|
||||||
@@ -182,7 +171,7 @@ export class VirtualizedCollection<TData> implements IObservableCollection<TData
|
|||||||
return currentData;
|
return currentData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getDataFromCurrent(index: number): TData {
|
private getDataFromCurrent(index: number): T {
|
||||||
if (this._bufferWindowBefore.contains(index)) {
|
if (this._bufferWindowBefore.contains(index)) {
|
||||||
return this._bufferWindowBefore.getItem(index);
|
return this._bufferWindowBefore.getItem(index);
|
||||||
} else if (this._bufferWindowAfter.contains(index)) {
|
} else if (this._bufferWindowAfter.contains(index)) {
|
||||||
@@ -191,39 +180,47 @@ export class VirtualizedCollection<TData> implements IObservableCollection<TData
|
|||||||
return this._window.getItem(index);
|
return this._window.getItem(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._placeHolderGenerator(index);
|
return this.placeHolderGenerator(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
private resetWindowsAroundIndex(index: number): void {
|
private resetWindowsAroundIndex(index: number): void {
|
||||||
|
|
||||||
let bufferWindowBeforeStart = Math.max(0, index - this._windowSize * 1.5);
|
let bufferWindowBeforeStart = Math.max(0, index - this.windowSize * 1.5);
|
||||||
let bufferWindowBeforeEnd = Math.max(0, index - this._windowSize / 2);
|
let bufferWindowBeforeEnd = Math.max(0, index - this.windowSize / 2);
|
||||||
this._bufferWindowBefore.positionWindow(bufferWindowBeforeStart, bufferWindowBeforeEnd - bufferWindowBeforeStart);
|
this._bufferWindowBefore.positionWindow(bufferWindowBeforeStart, bufferWindowBeforeEnd - bufferWindowBeforeStart);
|
||||||
|
|
||||||
let mainWindowStart = bufferWindowBeforeEnd;
|
let mainWindowStart = bufferWindowBeforeEnd;
|
||||||
let mainWindowEnd = Math.min(mainWindowStart + this._windowSize, this._length);
|
let mainWindowEnd = Math.min(mainWindowStart + this.windowSize, this.length);
|
||||||
this._window.positionWindow(mainWindowStart, mainWindowEnd - mainWindowStart);
|
this._window.positionWindow(mainWindowStart, mainWindowEnd - mainWindowStart);
|
||||||
|
|
||||||
let bufferWindowAfterStart = mainWindowEnd;
|
let bufferWindowAfterStart = mainWindowEnd;
|
||||||
let bufferWindowAfterEnd = Math.min(bufferWindowAfterStart + this._windowSize, this._length);
|
let bufferWindowAfterEnd = Math.min(bufferWindowAfterStart + this.windowSize, this.length);
|
||||||
this._bufferWindowAfter.positionWindow(bufferWindowAfterStart, bufferWindowAfterEnd - bufferWindowAfterStart);
|
this._bufferWindowAfter.positionWindow(bufferWindowAfterStart, bufferWindowAfterEnd - bufferWindowAfterStart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AsyncDataProvider<TData extends IGridDataRow> implements IDisposableDataProvider<TData> {
|
export class AsyncDataProvider<T extends Slick.SlickData> implements IDisposableDataProvider<T> {
|
||||||
|
|
||||||
constructor(private dataRows: IObservableCollection<TData>) { }
|
constructor(public dataRows: IObservableCollection<T>) { }
|
||||||
|
|
||||||
public getLength(): number {
|
public getLength(): number {
|
||||||
return this.dataRows ? this.dataRows.getLength() : 0;
|
return this.dataRows.getLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
public getItem(index: number): TData {
|
public getItem(index: number): T {
|
||||||
return !this.dataRows ? undefined : this.dataRows.at(index);
|
return this.dataRows.at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getRange(start: number, end: number): TData[] {
|
public getRange(start: number, end: number): T[] {
|
||||||
return !this.dataRows ? undefined : this.dataRows.getRange(start, end);
|
return this.dataRows.getRange(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
public set length(length: number) {
|
||||||
|
this.dataRows.setLength(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public get length(): number {
|
||||||
|
return this.dataRows.getLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { range } from 'vs/base/common/arrays';
|
|
||||||
|
|
||||||
export interface IRowNumberColumnOptions {
|
export interface IRowNumberColumnOptions {
|
||||||
numberOfRows: number;
|
numberOfRows: number;
|
||||||
cssClass?: string;
|
cssClass?: string;
|
||||||
@@ -17,7 +15,7 @@ const sizePerDigit = 15;
|
|||||||
export class RowNumberColumn<T> implements Slick.Plugin<T> {
|
export class RowNumberColumn<T> implements Slick.Plugin<T> {
|
||||||
private handler = new Slick.EventHandler();
|
private handler = new Slick.EventHandler();
|
||||||
private grid: Slick.Grid<T>;
|
private grid: Slick.Grid<T>;
|
||||||
|
private currentColumnWidth: number;
|
||||||
|
|
||||||
constructor(private options: IRowNumberColumnOptions) {
|
constructor(private options: IRowNumberColumnOptions) {
|
||||||
}
|
}
|
||||||
@@ -52,16 +50,22 @@ export class RowNumberColumn<T> implements Slick.Plugin<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public updateRowCount(rowNum: number) {
|
||||||
|
this.options.numberOfRows = rowNum;
|
||||||
|
let columnWidth = Math.max(this.options.numberOfRows.toString().length * sizePerDigit, 22);
|
||||||
|
if (columnWidth !== this.currentColumnWidth) {
|
||||||
|
this.grid.setColumnWidths([this.getColumnDefinition()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public getColumnDefinition(): Slick.Column<T> {
|
public getColumnDefinition(): Slick.Column<T> {
|
||||||
// that smallest we can make it is 22 due to padding and margins in the cells
|
// that smallest we can make it is 22 due to padding and margins in the cells
|
||||||
let columnWidth = Math.max(this.options.numberOfRows.toString().length * sizePerDigit, 22);
|
this.currentColumnWidth = Math.max(this.options.numberOfRows.toString().length * sizePerDigit, 22);
|
||||||
return {
|
return {
|
||||||
id: 'rowNumber',
|
id: 'rowNumber',
|
||||||
name: '',
|
name: '',
|
||||||
field: 'rowNumber',
|
field: 'rowNumber',
|
||||||
width: columnWidth,
|
width: this.currentColumnWidth,
|
||||||
minWidth: columnWidth,
|
|
||||||
maxWidth: columnWidth,
|
|
||||||
resizable: false,
|
resizable: false,
|
||||||
cssClass: this.options.cssClass,
|
cssClass: this.options.cssClass,
|
||||||
focusable: false,
|
focusable: false,
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
.carbon-taskbar {
|
.carbon-taskbar {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
margin: 2px 0px 2px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carbon-taskbar.monaco-toolbar .monaco-action-bar.animated .actions-container {
|
.carbon-taskbar.monaco-toolbar .monaco-action-bar.animated .actions-container {
|
||||||
@@ -39,11 +40,6 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.carbon-taskbar {
|
|
||||||
margin-top: 2px;
|
|
||||||
margin-bottom: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.carbon-taskbar .action-item {
|
.carbon-taskbar .action-item {
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
@@ -54,6 +50,11 @@
|
|||||||
padding-left: 15px;
|
padding-left: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.carbon-taskbar .action-item-label {
|
||||||
|
display: flex;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
.listDatabasesSelectBox {
|
.listDatabasesSelectBox {
|
||||||
padding-left: 2px;
|
padding-left: 2px;
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
|
|||||||
@@ -146,4 +146,5 @@ export class Taskbar {
|
|||||||
public dispose(): void {
|
public dispose(): void {
|
||||||
this.actionBar.dispose();
|
this.actionBar.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ export const NewQuery = 'NewQuery';
|
|||||||
export const FirewallRuleRequested = 'FirewallRuleCreated';
|
export const FirewallRuleRequested = 'FirewallRuleCreated';
|
||||||
export const DashboardNavigated = 'DashboardNavigated';
|
export const DashboardNavigated = 'DashboardNavigated';
|
||||||
|
|
||||||
|
|
||||||
// Telemetry Properties
|
// Telemetry Properties
|
||||||
|
|
||||||
// Modal Dialogs:
|
// Modal Dialogs:
|
||||||
@@ -42,3 +41,21 @@ export const Accounts = 'Accounts';
|
|||||||
export const FireWallRule = 'FirewallRule';
|
export const FireWallRule = 'FirewallRule';
|
||||||
export const AutoOAuth = 'AutoOAuth';
|
export const AutoOAuth = 'AutoOAuth';
|
||||||
export const AddNewDashboardTab = 'AddNewDashboardTab';
|
export const AddNewDashboardTab = 'AddNewDashboardTab';
|
||||||
|
|
||||||
|
// SQL Agent Events:
|
||||||
|
|
||||||
|
// Views
|
||||||
|
export const JobsView = 'JobsViewOpened';
|
||||||
|
export const JobHistoryView = 'JobHistoryViewOpened';
|
||||||
|
export const JobStepsView = 'JobStepsViewOpened';
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
export const RunAgentJob = 'RunAgentJob';
|
||||||
|
export const StopAgentJob = 'StopAgentJob';
|
||||||
|
export const DeleteAgentJob = 'DeleteAgentJob';
|
||||||
|
export const DeleteAgentJobStep = 'DeleteAgentJobStep';
|
||||||
|
export const DeleteAgentAlert = 'DeleteAgentAlert';
|
||||||
|
export const DeleteAgentOperator = 'DeleteAgentOperator';
|
||||||
|
export const DeleteAgentProxy = 'DeleteAgentProxy';
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,31 +4,10 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
import * as crypto from 'crypto';
|
|
||||||
import * as os from 'os';
|
|
||||||
import { ITelemetryService, ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
|
import { ITelemetryService, ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
|
||||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||||
import { warn } from 'sql/base/common/log';
|
import { warn } from 'sql/base/common/log';
|
||||||
|
|
||||||
import { generateUuid } from 'vs/base/common/uuid';
|
|
||||||
|
|
||||||
// Generate a unique, deterministic ID for the current user of the extension
|
|
||||||
export function generateUserId(): Promise<string> {
|
|
||||||
return new Promise<string>(resolve => {
|
|
||||||
try {
|
|
||||||
getmac.getMac((error, macAddress) => {
|
|
||||||
if (!error) {
|
|
||||||
resolve(crypto.createHash('sha256').update(macAddress + os.homedir(), 'utf8').digest('hex'));
|
|
||||||
} else {
|
|
||||||
resolve(generateUuid()); // fallback
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
resolve(generateUuid()); // fallback
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IConnectionTelemetryData extends ITelemetryData {
|
export interface IConnectionTelemetryData extends ITelemetryData {
|
||||||
provider?: string;
|
provider?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
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 |