Initial SQL Agent merge for March release (#961)

* WIP

* wip

* SQL Agent wip

* wip

* Initial control host (wip)

* Initial hookup of SQL Agent service to job component

* Update agent package.json

* Hook up getJobs call

* A couple job view updates

* Add some more agent views

* Rename some 'agent' classes to 'jobManagement'

* job history page (#852)

* added back button, run actions and overview accordion

* refactoring

* overview table complete

* fixed the dropdown arrow for the overview section

* added table for prev job list

* fixed agent job result type

* code cleaning and code review comments

* fixed yarn.lock conflicts

* added function for job history

* changed vscode-languageclient version

* changed yarn lock file

* fixed yarn lock file

* fixed yarn file

* fixed css paths

* added images to packaging step

* fix resource path for packaging

* Switch back getJobs return type

* Make enum const

* Remove sqlops const

* WIP

* WIP

* Feature/agent1 adbist (#899)

* added back button, run actions and overview accordion

* refactoring

* overview table complete

* fixed the dropdown arrow for the overview section

* added table for prev job list

* fixed agent job result type

* code cleaning and code review comments

* fixed yarn.lock conflicts

* added function for job history

* changed vscode-languageclient version

* changed yarn lock file

* fixed yarn lock file

* fixed yarn file

* fixed css paths

* added images to packaging step

* fix resource path for packaging

* added steps lists

* fixed style and dimensions

* fixed conflicts

* implemented job list

* added the Date and Status columns

* update yarn files

* merged feature/agent1

* added theme styling for light theme

* changed yarn lock files

* made job history page css more specific

* Add visiblity check to job view

* Clean up jobs styling and call getJobHistory

* Add more Job Table styling

* Enable detail view in job table

* Use updated slickgrid repo

* vbumped slickgrid

* Convert rowdetail slickgrid plug to TypeScript

* Feature/agent1 adbist (#945)

* added back button, run actions and overview accordion

* refactoring

* overview table complete

* fixed the dropdown arrow for the overview section

* added table for prev job list

* fixed agent job result type

* code cleaning and code review comments

* fixed yarn.lock conflicts

* added function for job history

* changed vscode-languageclient version

* changed yarn lock file

* fixed yarn lock file

* fixed yarn file

* fixed css paths

* added images to packaging step

* fix resource path for packaging

* added steps lists

* fixed style and dimensions

* fixed conflicts

* implemented job list

* added the Date and Status columns

* update yarn files

* merged feature/agent1

* added theme styling for light theme

* changed yarn lock files

* added method signatures for job history with DMP

* added methods for job running

* added job actions to sqlops

* Refer to dataprotocol from feature/agentDmp1 branch

* Update SQL Tools version to 1.4.0-alpha.13

* Change Feb to March in release note prompt

* SQL Agent extension metadata

* add feature explicitly in client creation

* Update Agent job registration

* Update package.json

* Feature/agent1 adbist (#955)

* added back button, run actions and overview accordion

* refactoring

* overview table complete

* fixed the dropdown arrow for the overview section

* added table for prev job list

* fixed agent job result type

* code cleaning and code review comments

* fixed yarn.lock conflicts

* added function for job history

* changed vscode-languageclient version

* changed yarn lock file

* fixed yarn lock file

* fixed yarn file

* fixed css paths

* added images to packaging step

* fix resource path for packaging

* added steps lists

* fixed style and dimensions

* fixed conflicts

* implemented job list

* added the Date and Status columns

* update yarn files

* merged feature/agent1

* added theme styling for light theme

* changed yarn lock files

* added method signatures for job history with DMP

* added methods for job running

* added job actions to sqlops

* navigation works but is really slow to load data

* Add jobs view icon

* Misc. cleanups
This commit is contained in:
Karl Burtram
2018-03-23 13:27:55 -07:00
committed by GitHub
parent 67a9ff3e16
commit 357bb1916e
59 changed files with 4741 additions and 275 deletions

View File

@@ -72,6 +72,7 @@ const vsce = require('vsce');
const sqlBuiltInExtensions = [
// Add SQL built-in extensions here.
// the extension will be excluded from SQLOps package and will have separate vsix packages
'agent'
];
const vscodeEntryPoints = _.flatten([
@@ -120,6 +121,7 @@ const vscodeResources = [
'out-build/sql/parts/grid/views/**/*.html',
'out-build/sql/parts/tasks/**/*.html',
'out-build/sql/parts/taskHistory/viewlet/media/**',
'out-build/sql/parts/jobManagement/common/media/*.svg',
'out-build/sql/media/objectTypes/*.svg',
'out-build/sql/media/icons/*.svg',
'!**/test/**'

View File

@@ -34,7 +34,8 @@ const extensions = [
'git',
'merge-conflict',
'insights-default',
'account-provider-azure'
'account-provider-azure',
'agent'
];
extensions.forEach(extension => yarnInstall(`extensions/${extension}`));

View File

@@ -27,8 +27,8 @@
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-0.0.29.tgz#fbcfd330573b912ef59eeee14602bface630754b"
"@types/node@*":
version "8.0.51"
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.51.tgz#b31d716fb8d58eeb95c068a039b9b6292817d5fb"
version "9.4.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-9.4.7.tgz#57d81cd98719df2c9de118f2d5f3b1120dcd7275"
"@types/node@8.0.33":
version "8.0.33"
@@ -44,13 +44,6 @@ agent-base@4, agent-base@^4.1.0:
dependencies:
es6-promisify "^5.0.0"
ajv@^4.9.1:
version "4.11.8"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
dependencies:
co "^4.6.0"
json-stable-stringify "^1.0.1"
ajv@^5.1.0:
version "5.5.2"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
@@ -170,19 +163,19 @@ aws4@^1.2.1, aws4@^1.6.0:
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
azure-storage@^2.1.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/azure-storage/-/azure-storage-2.6.0.tgz#84747ee54a4bd194bb960f89f3eff89d67acf1cf"
version "2.8.1"
resolved "https://registry.yarnpkg.com/azure-storage/-/azure-storage-2.8.1.tgz#ecb9d050ef1395e79ffbb652c02fe643687bec63"
dependencies:
browserify-mime "~1.2.9"
extend "~1.2.1"
json-edm-parser "0.1.2"
md5.js "1.3.4"
readable-stream "~2.0.0"
request "~2.81.0"
request "~2.83.0"
underscore "~1.8.3"
uuid "^3.0.0"
validator "~3.35.0"
xml2js "0.2.7"
validator "~9.4.1"
xml2js "0.2.8"
xmlbuilder "0.4.3"
balanced-match@^1.0.0:
@@ -242,8 +235,8 @@ boom@5.x.x:
hoek "4.x.x"
brace-expansion@^1.1.7:
version "1.1.8"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
dependencies:
balanced-match "^1.0.0"
concat-map "0.0.1"
@@ -319,12 +312,12 @@ clone@^2.1.1:
resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb"
cloneable-readable@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.0.0.tgz#a6290d413f217a61232f95e458ff38418cfb0117"
version "1.1.2"
resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.2.tgz#d591dee4a8f8bc15da43ce97dceeba13d43e2a65"
dependencies:
inherits "^2.0.1"
process-nextick-args "^1.0.6"
through2 "^2.0.1"
process-nextick-args "^2.0.0"
readable-stream "^2.3.5"
co@^4.6.0:
version "4.6.0"
@@ -334,9 +327,9 @@ color-support@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
combined-stream@^1.0.5, combined-stream@~1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009"
combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5:
version "1.0.6"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818"
dependencies:
delayed-stream "~1.0.0"
@@ -345,8 +338,8 @@ commander@2.11.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563"
commander@^2.9.0:
version "2.13.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c"
version "2.15.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.0.tgz#ad2a23a1c3b036e392469b8012cec6b33b4c1322"
commander@~2.8.1:
version "2.8.1"
@@ -384,9 +377,9 @@ dashdash@^1.12.0:
dependencies:
assert-plus "^1.0.0"
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.1.3":
version "0.1.3"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/5758b2a5804ea488d14326662f51d19cc970ccd0"
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.1.5":
version "0.1.5"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/21b0bacfc759689a6c280408528c6029a21b1abf"
dependencies:
vscode-languageclient "3.5.0"
@@ -394,12 +387,6 @@ dateformat@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062"
debug@2:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
dependencies:
ms "2.0.0"
debug@3.1.0, debug@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
@@ -488,8 +475,8 @@ duplexer@~0.1.1:
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
duplexify@^3.2.0:
version "3.5.3"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.3.tgz#8b5818800df92fd0125b27ab896491912858243e"
version "3.5.4"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.4.tgz#4bb46c1796eabebeec4ca9a2e66b808cb7a3d8b4"
dependencies:
end-of-stream "^1.0.0"
inherits "^2.0.1"
@@ -524,7 +511,7 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2:
event-stream@^3.3.1, event-stream@~3.3.4:
version "3.3.4"
resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
resolved "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
dependencies:
duplexer "~0.1.1"
from "~0"
@@ -569,7 +556,7 @@ extend@~1.2.1:
"extensions-modules@file:../extensions-modules":
version "0.1.0"
dependencies:
dataprotocol-client "github:Microsoft/sqlops-dataprotocolclient#0.1.3"
dataprotocol-client "github:Microsoft/sqlops-dataprotocolclient#0.1.5"
decompress "^4.2.0"
fs-extra-promise "^1.0.1"
http-proxy-agent "^2.0.0"
@@ -577,7 +564,7 @@ extend@~1.2.1:
opener "^1.4.3"
tmp "0.0.33"
vscode-extension-telemetry "0.0.8"
vscode-languageclient "^3.5.0"
vscode-languageclient "3.5.0"
extglob@^0.3.1:
version "0.3.2"
@@ -585,10 +572,14 @@ extglob@^0.3.1:
dependencies:
is-extglob "^1.0.0"
extsprintf@1.3.0, extsprintf@^1.2.0:
extsprintf@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
extsprintf@^1.2.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
fancy-log@^1.1.0:
version "1.3.2"
resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1"
@@ -598,8 +589,8 @@ fancy-log@^1.1.0:
time-stamp "^1.0.0"
fast-deep-equal@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff"
version "1.1.0"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614"
fast-json-stable-stringify@^2.0.0:
version "2.0.0"
@@ -664,11 +655,11 @@ form-data@~2.1.1:
mime-types "^2.1.12"
form-data@~2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf"
version "2.3.2"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099"
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.5"
combined-stream "1.0.6"
mime-types "^2.1.12"
from@~0:
@@ -900,10 +891,6 @@ gulplog@^1.0.0:
dependencies:
glogg "^1.0.0"
har-schema@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
har-schema@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
@@ -917,13 +904,6 @@ har-validator@~2.0.6:
is-my-json-valid "^2.12.4"
pinkie-promise "^2.0.0"
har-validator@~4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
dependencies:
ajv "^4.9.1"
har-schema "^1.0.5"
har-validator@~5.0.3:
version "5.0.3"
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd"
@@ -981,15 +961,15 @@ hoek@2.x.x:
resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
hoek@4.x.x:
version "4.2.0"
resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d"
version "4.2.1"
resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb"
http-proxy-agent@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.0.0.tgz#46482a2f0523a4d6082551709f469cb3e4a85ff4"
version "2.1.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
dependencies:
agent-base "4"
debug "2"
debug "3.1.0"
http-signature@~1.1.0:
version "1.1.1"
@@ -1008,15 +988,15 @@ http-signature@~1.2.0:
sshpk "^1.7.0"
https-proxy-agent@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.1.1.tgz#a7ce4382a1ba8266ee848578778122d491260fd9"
version "2.2.0"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.0.tgz#7fbba856be8cd677986f42ebd3664f6317257887"
dependencies:
agent-base "^4.1.0"
debug "^3.1.0"
ieee754@^1.1.4:
version "1.1.8"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
version "1.1.10"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.10.tgz#719a6f7b026831e64bdb838b0de1bb0029bbf716"
inflight@^1.0.4:
version "1.0.6"
@@ -1067,12 +1047,17 @@ is-glob@^3.1.0:
dependencies:
is-extglob "^2.1.0"
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.4:
version "2.17.1"
resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz#3da98914a70a22f0a8563ef1511a246c6fc55471"
version "2.17.2"
resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz#6b2103a288e94ef3de5cf15d29dd85fc4b78d65c"
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"
@@ -1164,7 +1149,7 @@ json-schema@0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1:
json-stable-stringify@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
dependencies:
@@ -1311,8 +1296,8 @@ lodash.templatesettings@^3.0.0:
lodash.escape "^3.0.0"
make-dir@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.1.0.tgz#19b4369fe48c116f53c2af95ad102c0e39e85d51"
version "1.2.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.2.0.tgz#6d6a49eead4aae296c53bbf3a1a008bd6c89469b"
dependencies:
pify "^3.0.0"
@@ -1351,19 +1336,19 @@ micromatch@^2.3.7:
parse-glob "^3.0.4"
regex-cache "^0.4.2"
mime-db@~1.30.0:
version "1.30.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01"
mime-db@~1.33.0:
version "1.33.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db"
mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7:
version "2.1.17"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a"
version "2.1.18"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8"
dependencies:
mime-db "~1.30.0"
mime-db "~1.33.0"
mime@^1.3.4:
version "1.4.1"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
version "1.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.4:
version "3.0.4"
@@ -1498,10 +1483,6 @@ pend@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
performance-now@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
performance-now@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
@@ -1542,7 +1523,11 @@ priorityqueuejs@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/priorityqueuejs/-/priorityqueuejs-1.0.0.tgz#2ee4f23c2560913e08c07ce5ccdd6de3df2c5af8"
process-nextick-args@^1.0.6, process-nextick-args@~1.0.6:
process-nextick-args@^2.0.0, process-nextick-args@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
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"
@@ -1554,10 +1539,6 @@ qs@~6.3.0:
version "6.3.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c"
qs@~6.4.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
qs@~6.5.1:
version "6.5.1"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
@@ -1594,14 +1575,14 @@ randomatic@^1.1.3:
isarray "0.0.1"
string_decoder "~0.10.x"
readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.1.5:
version "2.3.3"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.1.5, readable-stream@^2.3.5:
version "2.3.5"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.5.tgz#b4f85003a938cbb6ecbce2a124fb1012bd1a838d"
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.3"
isarray "~1.0.0"
process-nextick-args "~1.0.6"
process-nextick-args "~2.0.0"
safe-buffer "~5.1.1"
string_decoder "~1.0.3"
util-deprecate "~1.0.1"
@@ -1653,8 +1634,8 @@ replace-ext@^1.0.0:
resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb"
request@^2.83.0:
version "2.83.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356"
version "2.85.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.85.0.tgz#5a03615a47c61420b3eb99b7dba204f83603e1fa"
dependencies:
aws-sign2 "~0.7.0"
aws4 "^1.6.0"
@@ -1704,32 +1685,32 @@ request@~2.79.0:
tunnel-agent "~0.4.1"
uuid "^3.0.0"
request@~2.81.0:
version "2.81.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
request@~2.83.0:
version "2.83.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356"
dependencies:
aws-sign2 "~0.6.0"
aws4 "^1.2.1"
aws-sign2 "~0.7.0"
aws4 "^1.6.0"
caseless "~0.12.0"
combined-stream "~1.0.5"
extend "~3.0.0"
extend "~3.0.1"
forever-agent "~0.6.1"
form-data "~2.1.1"
har-validator "~4.2.1"
hawk "~3.1.3"
http-signature "~1.1.0"
form-data "~2.3.1"
har-validator "~5.0.3"
hawk "~6.0.2"
http-signature "~1.2.0"
is-typedarray "~1.0.0"
isstream "~0.1.2"
json-stringify-safe "~5.0.1"
mime-types "~2.1.7"
oauth-sign "~0.8.1"
performance-now "^0.2.0"
qs "~6.4.0"
safe-buffer "^5.0.1"
stringstream "~0.0.4"
tough-cookie "~2.3.0"
mime-types "~2.1.17"
oauth-sign "~0.8.2"
performance-now "^2.1.0"
qs "~6.5.1"
safe-buffer "^5.1.1"
stringstream "~0.0.5"
tough-cookie "~2.3.3"
tunnel-agent "^0.6.0"
uuid "^3.0.0"
uuid "^3.1.0"
requires-port@~1.0.0:
version "1.0.0"
@@ -1745,9 +1726,9 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
sax@0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.2.tgz#735ffaa39a1cff8ffb9598f0223abdb03a9fb2ea"
sax@0.5.x:
version "0.5.8"
resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.8.tgz#d472db228eb331c2506b0e8c15524adb939d12c1"
sax@>=0.6.0:
version "1.2.4"
@@ -1780,8 +1761,8 @@ sntp@2.x.x:
hoek "4.x.x"
source-map-support@^0.5.0:
version "0.5.2"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.2.tgz#1a6297fd5b2e762b39688c7fc91233b60984f0a5"
version "0.5.4"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.4.tgz#54456efa89caa9270af7cd624cc2f123e51fbae8"
dependencies:
source-map "^0.6.0"
@@ -1800,8 +1781,8 @@ split@0.3:
through "2"
sshpk@^1.7.0:
version "1.13.1"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3"
version "1.14.1"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.1.tgz#130f5975eddad963f1d56f92b9ac6c51fa9f83eb"
dependencies:
asn1 "~0.2.3"
assert-plus "^1.0.0"
@@ -1917,7 +1898,7 @@ through2@^0.6.0, through2@~0.6.5:
readable-stream ">=1.0.33-1 <1.1.0-0"
xtend ">=4.0.0 <4.1.0-0"
through2@^2.0.0, through2@^2.0.1, through2@^2.0.3, through2@~2.0.0, through2@~2.0.3:
through2@^2.0.0, through2@^2.0.3, through2@~2.0.0, through2@~2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be"
dependencies:
@@ -1945,8 +1926,8 @@ to-absolute-glob@^0.1.1:
extend-shallow "^2.0.1"
tough-cookie@~2.3.0, tough-cookie@~2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561"
version "2.3.4"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655"
dependencies:
punycode "^1.4.1"
@@ -1997,11 +1978,7 @@ 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.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04"
uuid@^3.1.0:
uuid@^3.0.0, uuid@^3.1.0:
version "3.2.1"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14"
@@ -2009,9 +1986,9 @@ vali-date@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6"
validator@~3.35.0:
version "3.35.0"
resolved "https://registry.yarnpkg.com/validator/-/validator-3.35.0.tgz#3f07249402c1fc8fc093c32c6e43d72a79cca1dc"
validator@~9.4.1:
version "9.4.1"
resolved "https://registry.yarnpkg.com/validator/-/validator-9.4.1.tgz#abf466d398b561cd243050112c6ff1de6cc12663"
verror@1.10.0:
version "1.10.0"
@@ -2103,30 +2080,30 @@ vscode-extension-telemetry@0.0.8:
applicationinsights "0.18.0"
winreg "1.2.3"
vscode-jsonrpc@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0.tgz#87239d9e166b2d7352245b8a813597804c1d63aa"
vscode-jsonrpc@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-3.6.0.tgz#848d56995d5168950d84feb5d9c237ae5c6a02d4"
vscode-languageclient@3.5.0, vscode-languageclient@^3.5.0:
vscode-languageclient@3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-3.5.0.tgz#36d02cc186a8365a4467719a290fb200a9ae490a"
dependencies:
vscode-languageserver-protocol "^3.5.0"
vscode-languageserver-protocol@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.0.tgz#067c5cbe27709795398d119692c97ebba1452209"
version "3.6.0"
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.6.0.tgz#579642cdcccf74b0cd771c33daa3239acb40d040"
dependencies:
vscode-jsonrpc "^3.5.0"
vscode-languageserver-types "^3.5.0"
vscode-jsonrpc "^3.6.0"
vscode-languageserver-types "^3.6.0"
vscode-languageserver-types@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0.tgz#e48d79962f0b8e02de955e3f524908e2b19c0374"
vscode-languageserver-types@^3.6.0:
version "3.6.1"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.6.1.tgz#4bc06a48dff653495f12f94b8b1e228988a1748d"
vscode@^1.0.1:
version "1.1.10"
resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.10.tgz#d1cba378ab24f1d3ddf9cd470d242ee1472dd35b"
version "1.1.13"
resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.13.tgz#dcea0c5f3ec1ff6eca333216b4b20dd994d18d9a"
dependencies:
glob "^7.1.2"
gulp-chmod "^2.0.0"
@@ -2151,11 +2128,11 @@ wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
xml2js@0.2.7:
version "0.2.7"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.2.7.tgz#1838518bb01741cae0878bab4915e494c32306af"
xml2js@0.2.8:
version "0.2.8"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.2.8.tgz#9b81690931631ff09d1957549faf54f4f980b3c2"
dependencies:
sax "0.5.2"
sax "0.5.x"
xml2js@^0.4.17:
version "0.4.19"
@@ -2169,8 +2146,8 @@ xmlbuilder@0.4.3:
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-0.4.3.tgz#c4614ba74e0ad196e609c9272cd9e1ddb28a8a58"
xmlbuilder@~9.0.1:
version "9.0.4"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.4.tgz#519cb4ca686d005a8420d3496f3f0caeecca580f"
version "9.0.7"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1:
version "4.0.1"

View File

@@ -1,7 +1,7 @@
{
"name": "extensions-modules",
"version": "0.1.0",
"description": "Shared modules for Carbon extensions",
"description": "Shared modules for SQL Operations Studio extensions",
"dependencies": {
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.1.5",
"decompress": "^4.2.0",
@@ -11,7 +11,7 @@
"opener": "^1.4.3",
"tmp": "0.0.33",
"vscode-extension-telemetry": "0.0.8",
"vscode-languageclient": "^3.5.0"
"vscode-languageclient": "3.5.0"
},
"devDependencies": {
"@types/node": "^6.0.61",

View File

@@ -5,7 +5,7 @@
'use strict';
import { ExtensionContext, workspace, window, OutputChannel, languages } from 'vscode';
import { SqlOpsDataClient, ClientOptions } from 'dataprotocol-client';
import * as SqlopsClient from 'dataprotocol-client';
import { CloseAction, ErrorAction, ServerOptions, NotificationHandler, NotificationType, RequestType, TransportKind } from 'vscode-languageclient';
import { VscodeWrapper } from '../controllers/vscodeWrapper';
@@ -132,14 +132,14 @@ export class SqlToolsServiceClient {
}
// VS Code Language Client
private _client: SqlOpsDataClient = undefined;
private _client: SqlopsClient.SqlOpsDataClient = undefined;
// getter method for the Language Client
private get client(): SqlOpsDataClient {
private get client(): SqlopsClient.SqlOpsDataClient {
return this._client;
}
private set client(client: SqlOpsDataClient) {
private set client(client: SqlopsClient.SqlOpsDataClient) {
this._client = client;
}
@@ -317,9 +317,9 @@ export class SqlToolsServiceClient {
}
}
public createClient(context: ExtensionContext, runtimeId: Runtime, languageClientHelper: LanguageServiceContracts.ILanguageClientHelper, executableFiles: string[]): Promise<SqlOpsDataClient> {
return new Promise<SqlOpsDataClient>((resolve, reject) => {
let client: SqlOpsDataClient;
public createClient(context: ExtensionContext, runtimeId: Runtime, languageClientHelper: LanguageServiceContracts.ILanguageClientHelper, executableFiles: string[]): Promise<SqlopsClient.SqlOpsDataClient> {
return new Promise<SqlopsClient.SqlOpsDataClient>((resolve, reject) => {
let client: SqlopsClient.SqlOpsDataClient;
this._server.findServerPath(this.installDirectory, executableFiles).then(serverPath => {
if (serverPath === undefined) {
reject(new Error(SqlToolsServiceClient._constants.invalidServiceFilePath));
@@ -329,7 +329,7 @@ export class SqlToolsServiceClient {
languageClientHelper.createServerOptions(serverPath, runtimeId) : this.createServerOptions(serverPath);
// Options to control the language client
let clientOptions: ClientOptions = {
let clientOptions: SqlopsClient.ClientOptions = {
documentSelector: [SqlToolsServiceClient._constants.languageId],
providerId: '',
synchronize: {
@@ -357,7 +357,7 @@ export class SqlToolsServiceClient {
this._serviceStatus.showServiceLoading();
// cache the client instance for later use
client = new SqlOpsDataClient(SqlToolsServiceClient._constants.serviceName, serverOptions, clientOptions);
client = new SqlopsClient.SqlOpsDataClient(SqlToolsServiceClient._constants.serviceName, serverOptions, clientOptions);
if (context !== undefined) {
// Create the language client and start the client.
@@ -404,9 +404,9 @@ export class SqlToolsServiceClient {
return serverOptions;
}
private createLanguageClient(serverOptions: ServerOptions): SqlOpsDataClient {
private createLanguageClient(serverOptions: ServerOptions): SqlopsClient.SqlOpsDataClient {
// Options to control the language client
let clientOptions: ClientOptions = {
let clientOptions: SqlopsClient.ClientOptions = {
documentSelector: [SqlToolsServiceClient._constants.languageId],
providerId: SqlToolsServiceClient._constants.providerId,
synchronize: {
@@ -427,12 +427,28 @@ export class SqlToolsServiceClient {
name: '',
show: () => {
}
}
},
features: [
SqlopsClient.AdminServicesFeature,
SqlopsClient.BackupFeature,
SqlopsClient.CapabilitiesFeature,
SqlopsClient.ConnectionFeature,
SqlopsClient.FileBrowserFeature,
SqlopsClient.MetadataFeature,
SqlopsClient.ObjectExplorerFeature,
SqlopsClient.ProfilerFeature,
SqlopsClient.QueryFeature,
SqlopsClient.RestoreFeature,
SqlopsClient.ScriptingFeature,
SqlopsClient.TaskServicesFeature,
// heres the important bit
LanguageServiceContracts.AgentServicesFeature
]
};
this._serviceStatus.showServiceLoading();
// cache the client instance for later use
let client = new SqlOpsDataClient(SqlToolsServiceClient._constants.serviceName, serverOptions, clientOptions);
let client = new SqlopsClient.SqlOpsDataClient(SqlToolsServiceClient._constants.serviceName, serverOptions, clientOptions);
client.onReady().then(() => {
this.checkServiceCompatibility();
this._serviceStatus.showServiceLoaded();
@@ -478,7 +494,7 @@ export class SqlToolsServiceClient {
* @param params The params to pass with the request
* @returns A thenable object for when the request receives a response
*/
public sendRequest<P, R, E, RO>(type: RequestType<P, R, E, RO>, params?: P, client: SqlOpsDataClient = undefined): Thenable<R> {
public sendRequest<P, R, E, RO>(type: RequestType<P, R, E, RO>, params?: P, client: SqlopsClient.SqlOpsDataClient = undefined): Thenable<R> {
if (client === undefined) {
client = this._client;
}
@@ -492,7 +508,7 @@ export class SqlToolsServiceClient {
* @param type The notification type to register the handler for
* @param handler The handler to register
*/
public onNotification<P, RO>(type: NotificationType<P, RO>, handler: NotificationHandler<P>, client: SqlOpsDataClient = undefined): void {
public onNotification<P, RO>(type: NotificationType<P, RO>, handler: NotificationHandler<P>, client: SqlopsClient.SqlOpsDataClient = undefined): void {
if (client === undefined) {
client = this._client;
}

View File

@@ -2,9 +2,13 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { NotificationType, ServerOptions } from 'vscode-languageclient';
import { NotificationType, ServerOptions, RequestType, RPCMessageType, ClientCapabilities, ServerCapabilities } from 'vscode-languageclient';
import { ITelemetryEventProperties, ITelemetryEventMeasures } from '../telemetry';
import { Runtime } from '../platform';
import { SqlOpsFeature, SqlOpsDataClient } from 'dataprotocol-client';
import * as sqlops from 'sqlops';
import * as UUID from 'vscode-languageclient/lib/utils/uuid';
import { Disposable } from 'vscode';
// ------------------------------- < Telemetry Sent Event > ------------------------------------
@@ -56,4 +60,120 @@ export class StatusChangeParams {
export interface ILanguageClientHelper {
createServerOptions(servicePath: string, runtimeId?: Runtime): ServerOptions;
}
}
// Job Management types
export interface AgentJobsParams {
ownerUri: string;
jobId: string;
}
export interface AgentJobsResult {
succeeded: boolean;
errorMessage: string;
jobs: sqlops.AgentJobInfo[];
}
export interface AgentJobHistoryParams {
ownerUri: string;
jobId: string;
}
export interface AgentJobHistoryResult {
succeeded: boolean;
errorMessage: string;
jobs: sqlops.AgentJobHistoryInfo[];
}
export interface AgentJobActionParams {
ownerUri: string;
jobName: string;
action: string;
}
export interface AgentJobActionResult {
succeeded: boolean;
errorMessage: string;
}
export namespace AgentJobsRequest {
export const type = new RequestType<AgentJobsParams, AgentJobsResult, void, void>('agent/jobs');
}
export namespace AgentJobHistoryRequest {
export const type = new RequestType<AgentJobHistoryParams, AgentJobHistoryResult, void, void>('agent/jobhistory');
}
export namespace AgentJobActionRequest {
export const type = new RequestType<AgentJobActionParams, AgentJobActionResult, void, void>('agent/jobaction');
}
export class AgentServicesFeature extends SqlOpsFeature<undefined> {
private static readonly messagesTypes: RPCMessageType[] = [
AgentJobsRequest.type,
AgentJobHistoryRequest.type,
AgentJobActionRequest.type
];
constructor(client: SqlOpsDataClient) {
super(client, AgentServicesFeature.messagesTypes);
}
public fillClientCapabilities(capabilities: ClientCapabilities): void {
// this isn't explicitly necessary
// ensure(ensure(capabilities, 'connection')!, 'agentServices')!.dynamicRegistration = true;
}
public initialize(capabilities: ServerCapabilities): void {
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: undefined
});
}
protected registerProvider(options: undefined): Disposable {
const client = this._client;
let getJobs = (ownerUri: string): Thenable<sqlops.AgentJobsResult> => {
let params: AgentJobsParams = { ownerUri: ownerUri, jobId: null };
return client.sendRequest(AgentJobsRequest.type, params).then(
r => r,
e => {
client.logFailedRequest(AgentJobsRequest.type, e);
return Promise.resolve(undefined);
}
);
};
let getJobHistory = (connectionUri: string, jobID: string): Thenable<sqlops.AgentJobHistoryResult> => {
let params: AgentJobHistoryParams = { ownerUri: connectionUri, jobId: jobID };
return client.sendRequest(AgentJobHistoryRequest.type, params).then(
r => r,
e => {
client.logFailedRequest(AgentJobHistoryRequest.type, e);
return Promise.resolve(undefined);
}
);
};
let jobAction = (connectionUri: string, jobName: string, action: string): Thenable<sqlops.AgentJobActionResult> => {
let params: AgentJobActionParams = { ownerUri: connectionUri, jobName: jobName, action: action };
return client.sendRequest(AgentJobActionRequest.type, params).then(
r => r,
e => {
client.logFailedRequest(AgentJobActionRequest.type, e);
return Promise.resolve(undefined);
}
);
};
return sqlops.dataprotocol.registerAgentServicesProvider({
providerId: client.providerId,
getJobs,
getJobHistory,
jobAction
});
}
}

View File

@@ -912,8 +912,8 @@ https-proxy-agent@^2.1.0:
debug "^3.1.0"
ieee754@^1.1.4:
version "1.1.8"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
version "1.1.10"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.10.tgz#719a6f7b026831e64bdb838b0de1bb0029bbf716"
inflight@^1.0.4:
version "1.0.6"
@@ -1941,24 +1941,24 @@ vscode-extension-telemetry@0.0.8:
applicationinsights "0.18.0"
winreg "1.2.3"
vscode-jsonrpc@^3.5.0:
vscode-jsonrpc@3.5.0, vscode-jsonrpc@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0.tgz#87239d9e166b2d7352245b8a813597804c1d63aa"
vscode-languageclient@3.5.0, vscode-languageclient@^3.5.0:
vscode-languageclient@3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-3.5.0.tgz#36d02cc186a8365a4467719a290fb200a9ae490a"
dependencies:
vscode-languageserver-protocol "^3.5.0"
vscode-languageserver-protocol@^3.5.0:
vscode-languageserver-protocol@3.5.0, vscode-languageserver-protocol@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.0.tgz#067c5cbe27709795398d119692c97ebba1452209"
dependencies:
vscode-jsonrpc "^3.5.0"
vscode-languageserver-types "^3.5.0"
vscode-languageserver-types@^3.5.0:
vscode-languageserver-types@3.5.0, vscode-languageserver-types@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0.tgz#e48d79962f0b8e02de955e3f524908e2b19c0374"

View File

@@ -0,0 +1,2 @@
client/src/**
client/tsconfig.json

View File

@@ -0,0 +1,23 @@
# Microsoft SQL Server Agent for SQL Operations Studio
Welcome to Microsoft SQL Server Agent for SQL Operations Studio! An extension for managing and troubleshooting
SQL Server Agent jobs and configuration. The current is a very early release of this extension that provides
basic functionality for the following.
* List SQL Server Agent Jobs configured on a SQL Server
* View Job History with job execution results
* Basic Job Control to start and stop jobs
## 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/sqlopsstudio/master/LICENSE.txt).

View File

@@ -0,0 +1,63 @@
/*---------------------------------------------------------------------------------------------
* 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 data from 'sqlops';
/**
* Wrapper class to act as a facade over VSCode and Data APIs and allow us to test / mock callbacks into
* this API from our code
*
* @export
* @class ApiWrapper
*/
export class ApiWrapper {
// Data APIs
public registerWebviewProvider(widgetId: string, handler: (webview: data.DashboardWebview) => void): void {
return data.dashboard.registerWebviewProvider(widgetId, handler);
}
public registerControlHostProvider(widgetId: string, handler: (webview: data.DashboardWebview) => void): void {
return data.dashboard.registerWebviewProvider(widgetId, handler);
}
/**
* Get the configuration for a extensionName
* @param extensionName The string name of the extension to get the configuration for
* @param resource The optional URI, as a URI object or a string, to use to get resource-scoped configurations
*/
public getConfiguration(extensionName: string, resource?: vscode.Uri | string): vscode.WorkspaceConfiguration {
if (typeof resource === 'string') {
try {
resource = this.parseUri(resource);
} catch (e) {
resource = undefined;
}
}
return vscode.workspace.getConfiguration(extensionName, resource as vscode.Uri);
}
/**
* Parse uri
*/
public parseUri(uri: string): vscode.Uri {
return vscode.Uri.parse(uri);
}
public showOpenDialog(options: vscode.OpenDialogOptions): Thenable<vscode.Uri[] | undefined> {
return vscode.window.showOpenDialog(options);
}
public showErrorMessage(message: string, ...items: string[]): Thenable<string | undefined> {
return vscode.window.showErrorMessage(message, ...items);
}
public get workspaceRootPath(): string {
return vscode.workspace.rootPath;
}
}

View File

@@ -0,0 +1,23 @@
/*---------------------------------------------------------------------------------------------
* 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 vscode = require('vscode');
import { MainController } from './mainController';
import { ApiWrapper } from './apiWrapper';
export let controller: MainController;
export function activate(context: vscode.ExtensionContext) {
let apiWrapper = new ApiWrapper();
controller = new MainController(context, apiWrapper);
controller.activate();
}
// this method is called when your extension is deactivated
export function deactivate(): void {
if (controller) {
controller.deactivate();
}
}

View File

@@ -0,0 +1,38 @@
/*---------------------------------------------------------------------------------------------
* 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 data from 'sqlops';
import { ApiWrapper } from './apiWrapper';
/**
* The main controller class that initializes the extension
*/
export class MainController {
protected _apiWrapper: ApiWrapper;
protected _context: vscode.ExtensionContext;
// PUBLIC METHODS //////////////////////////////////////////////////////
public constructor(context: vscode.ExtensionContext, apiWrapper?: ApiWrapper) {
this._apiWrapper = apiWrapper || new ApiWrapper();
this._context = context;
console.log('Got: ' + apiWrapper);
}
/**
* Deactivates the extension
*/
public deactivate(): void {
}
public activate(): void {
this._apiWrapper.registerWebviewProvider('data-management-agent', webview => {
webview.html = '<div><h1>SQL Agent</h1></div>';
});
}
}

View File

@@ -0,0 +1,8 @@
/*---------------------------------------------------------------------------------------------
* 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/vs/vscode.d.ts'/>
/// <reference path='../../../../../src/sql/sqlops.d.ts'/>
/// <reference types='@types/node'/>

View File

@@ -0,0 +1,19 @@
{
"compileOnSave": true,
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"outDir": "./out",
"lib": [
"es6", "es2015.promise"
],
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"declaration": true
},
"exclude": [
"node_modules"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@@ -0,0 +1,46 @@
{
"name": "agent",
"displayName": "SQL Server Agent",
"description": "Manage and troubleshoot SQL Agent jobs (early preview)",
"version": "0.27.0",
"publisher": "Microsoft",
"preview": true,
"license": "https://raw.githubusercontent.com/Microsoft/sqlopsstudio/master/LICENSE.txt",
"icon": "images/sqlserver.png",
"aiKey": "AIF-5574968e-856d-40d2-af67-c89a14e76412",
"engines": {
"vscode": "0.10.x"
},
"activationEvents": [
"*"
],
"main": "./client/out/main",
"scripts": {
"compile": "gulp compile-extension:agent-client"
},
"repository": {
"type": "git",
"url": "https://github.com/Microsoft/sqlopsstudio.git"
},
"contributes": {
"outputChannels": [
"sqlagent"
],
"dashboard.tabs": [
{
"id": "data-management-agent",
"description": "Manage and troubleshoot SQL Agent jobs",
"provider": "MSSQL",
"title": "SQL Agent",
"container": {
"controlhost-container": {
"type": "agent"
}
}
}
]
},
"devDependencies": {
"vscode": "1.0.1"
}
}

2085
extensions/agent/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,8 @@
"publisher": "Microsoft",
"aiKey": "AIF-5574968e-856d-40d2-af67-c89a14e76412",
"engines": {
"vscode": "0.10.x"
"vscode": "0.10.x",
"sqlops": "feature/agent1"
},
"activationEvents": [
"*"

View File

@@ -168,8 +168,8 @@ boom@5.x.x:
hoek "4.x.x"
brace-expansion@^1.1.7:
version "1.1.8"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
dependencies:
balanced-match "^1.0.0"
concat-map "0.0.1"
@@ -258,12 +258,12 @@ clone@^1.0.0:
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.3.tgz#298d7e2231660f40c003c2ed3140decf3f53085f"
cloneable-readable@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.0.0.tgz#a6290d413f217a61232f95e458ff38418cfb0117"
version "1.1.2"
resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.2.tgz#d591dee4a8f8bc15da43ce97dceeba13d43e2a65"
dependencies:
inherits "^2.0.1"
process-nextick-args "^1.0.6"
through2 "^2.0.1"
process-nextick-args "^2.0.0"
readable-stream "^2.3.5"
co@^4.6.0:
version "4.6.0"
@@ -273,9 +273,9 @@ color-support@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
combined-stream@^1.0.5, combined-stream@~1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009"
combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5:
version "1.0.6"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818"
dependencies:
delayed-stream "~1.0.0"
@@ -288,8 +288,8 @@ commander@2.3.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873"
commander@^2.9.0:
version "2.13.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c"
version "2.15.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.0.tgz#ad2a23a1c3b036e392469b8012cec6b33b4c1322"
commander@~2.8.1:
version "2.8.1"
@@ -333,9 +333,9 @@ dashdash@^1.12.0:
dependencies:
assert-plus "^1.0.0"
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.1.3":
version "0.1.3"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/5758b2a5804ea488d14326662f51d19cc970ccd0"
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.1.5":
version "0.1.5"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/21b0bacfc759689a6c280408528c6029a21b1abf"
dependencies:
vscode-languageclient "3.5.0"
@@ -350,19 +350,13 @@ dateformat@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062"
debug@2:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
dependencies:
ms "2.0.0"
debug@2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da"
dependencies:
ms "0.7.1"
debug@^3.1.0:
debug@3.1.0, debug@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
dependencies:
@@ -445,8 +439,8 @@ duplexer@~0.1.1:
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
duplexify@^3.2.0:
version "3.5.3"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.3.tgz#8b5818800df92fd0125b27ab896491912858243e"
version "3.5.4"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.4.tgz#4bb46c1796eabebeec4ca9a2e66b808cb7a3d8b4"
dependencies:
end-of-stream "^1.0.0"
inherits "^2.0.1"
@@ -491,7 +485,7 @@ escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2:
event-stream@^3.3.1, event-stream@~3.3.4:
version "3.3.4"
resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
resolved "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
dependencies:
duplexer "~0.1.1"
from "~0"
@@ -503,7 +497,7 @@ event-stream@^3.3.1, event-stream@~3.3.4:
event-stream@~3.1.5:
version "3.1.7"
resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.1.7.tgz#b4c540012d0fe1498420f3d8946008db6393c37a"
resolved "http://registry.npmjs.org/event-stream/-/event-stream-3.1.7.tgz#b4c540012d0fe1498420f3d8946008db6393c37a"
dependencies:
duplexer "~0.1.1"
from "~0"
@@ -538,7 +532,7 @@ extend@^3.0.0, extend@~3.0.0, extend@~3.0.1:
"extensions-modules@file:../../extensions-modules":
version "0.1.0"
dependencies:
dataprotocol-client "github:Microsoft/sqlops-dataprotocolclient#0.1.3"
dataprotocol-client "github:Microsoft/sqlops-dataprotocolclient#0.1.5"
decompress "^4.2.0"
fs-extra-promise "^1.0.1"
http-proxy-agent "^2.0.0"
@@ -546,7 +540,7 @@ extend@^3.0.0, extend@~3.0.0, extend@~3.0.1:
opener "^1.4.3"
tmp "0.0.33"
vscode-extension-telemetry "0.0.8"
vscode-languageclient "^3.5.0"
vscode-languageclient "3.5.0"
extglob@^0.3.1:
version "0.3.2"
@@ -571,8 +565,8 @@ fancy-log@^1.1.0:
time-stamp "^1.0.0"
fast-deep-equal@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff"
version "1.1.0"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614"
fast-json-stable-stringify@^2.0.0:
version "2.0.0"
@@ -644,11 +638,11 @@ form-data@~2.1.1:
mime-types "^2.1.12"
form-data@~2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf"
version "2.3.2"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099"
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.5"
combined-stream "1.0.6"
mime-types "^2.1.12"
from@~0:
@@ -971,19 +965,19 @@ hoek@2.x.x:
resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
hoek@4.x.x:
version "4.2.0"
resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d"
version "4.2.1"
resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb"
hosted-git-info@^2.1.4:
version "2.5.0"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c"
version "2.6.0"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.6.0.tgz#23235b29ab230c576aab0d4f13fc046b0b038222"
http-proxy-agent@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.0.0.tgz#46482a2f0523a4d6082551709f469cb3e4a85ff4"
version "2.1.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
dependencies:
agent-base "4"
debug "2"
debug "3.1.0"
http-signature@~1.1.0:
version "1.1.1"
@@ -1002,15 +996,15 @@ http-signature@~1.2.0:
sshpk "^1.7.0"
https-proxy-agent@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.1.1.tgz#a7ce4382a1ba8266ee848578778122d491260fd9"
version "2.2.0"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.0.tgz#7fbba856be8cd677986f42ebd3664f6317257887"
dependencies:
agent-base "^4.1.0"
debug "^3.1.0"
ieee754@^1.1.4:
version "1.1.8"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
version "1.1.10"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.10.tgz#719a6f7b026831e64bdb838b0de1bb0029bbf716"
indent-string@^2.1.0:
version "2.1.0"
@@ -1083,12 +1077,17 @@ is-glob@^3.1.0:
dependencies:
is-extglob "^2.1.0"
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.4:
version "2.17.1"
resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz#3da98914a70a22f0a8563ef1511a246c6fc55471"
version "2.17.2"
resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz#6b2103a288e94ef3de5cf15d29dd85fc4b78d65c"
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"
@@ -1486,15 +1485,15 @@ micromatch@^2.3.7:
parse-glob "^3.0.4"
regex-cache "^0.4.2"
mime-db@~1.30.0:
version "1.30.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01"
mime-db@~1.33.0:
version "1.33.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db"
mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7:
version "2.1.17"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a"
version "2.1.18"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8"
dependencies:
mime-db "~1.30.0"
mime-db "~1.33.0"
minimatch@0.3:
version "0.3.0"
@@ -1570,8 +1569,8 @@ multipipe@^0.1.0, multipipe@^0.1.2:
duplexer2 "0.0.2"
natives@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.1.tgz#011acce1f7cbd87f7ba6b3093d6cd9392be1c574"
version "1.1.2"
resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.2.tgz#4437ca1ed8a7f047531ccdfaf2792853df4efa1c"
node.extend@~1.1.2:
version "1.1.6"
@@ -1715,9 +1714,9 @@ preserve@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
process-nextick-args@^1.0.6, 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"
process-nextick-args@^2.0.0, process-nextick-args@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
punycode@^1.4.1:
version "1.4.1"
@@ -1768,14 +1767,14 @@ read-pkg@^1.0.0:
isarray "0.0.1"
string_decoder "~0.10.x"
readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.1.5:
version "2.3.3"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.1.5, readable-stream@^2.3.5:
version "2.3.5"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.5.tgz#b4f85003a938cbb6ecbce2a124fb1012bd1a838d"
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.3"
isarray "~1.0.0"
process-nextick-args "~1.0.6"
process-nextick-args "~2.0.0"
safe-buffer "~5.1.1"
string_decoder "~1.0.3"
util-deprecate "~1.0.1"
@@ -1829,8 +1828,8 @@ replace-ext@^1.0.0:
resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb"
request@^2.67.0:
version "2.83.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356"
version "2.85.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.85.0.tgz#5a03615a47c61420b3eb99b7dba204f83603e1fa"
dependencies:
aws-sign2 "~0.7.0"
aws4 "^1.6.0"
@@ -1936,19 +1935,27 @@ sparkles@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3"
spdx-correct@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40"
spdx-correct@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82"
dependencies:
spdx-license-ids "^1.0.2"
spdx-expression-parse "^3.0.0"
spdx-license-ids "^3.0.0"
spdx-expression-parse@~1.0.0:
version "1.0.4"
resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c"
spdx-exceptions@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9"
spdx-license-ids@^1.0.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57"
spdx-expression-parse@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0"
dependencies:
spdx-exceptions "^2.1.0"
spdx-license-ids "^3.0.0"
spdx-license-ids@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87"
split@0.2:
version "0.2.10"
@@ -1963,8 +1970,8 @@ split@0.3:
through "2"
sshpk@^1.7.0:
version "1.13.1"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3"
version "1.14.1"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.1.tgz#130f5975eddad963f1d56f92b9ac6c51fa9f83eb"
dependencies:
asn1 "~0.2.3"
assert-plus "^1.0.0"
@@ -2101,7 +2108,7 @@ through2@^0.6.0, through2@^0.6.3, through2@~0.6.5:
readable-stream ">=1.0.33-1 <1.1.0-0"
xtend ">=4.0.0 <4.1.0-0"
through2@^2.0.0, through2@^2.0.1, through2@^2.0.3, through2@~2.0.0, through2@~2.0.3:
through2@^2.0.0, through2@^2.0.3, through2@~2.0.0, through2@~2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be"
dependencies:
@@ -2140,8 +2147,8 @@ to-iso-string@0.0.2:
resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1"
tough-cookie@~2.3.0, tough-cookie@~2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561"
version "2.3.4"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655"
dependencies:
punycode "^1.4.1"
@@ -2190,11 +2197,11 @@ vali-date@^1.0.0:
resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6"
validate-npm-package-license@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"
version "3.0.3"
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338"
dependencies:
spdx-correct "~1.0.0"
spdx-expression-parse "~1.0.0"
spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0"
verror@1.10.0:
version "1.10.0"
@@ -2281,26 +2288,26 @@ vscode-extension-telemetry@0.0.8:
applicationinsights "0.18.0"
winreg "1.2.3"
vscode-jsonrpc@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0.tgz#87239d9e166b2d7352245b8a813597804c1d63aa"
vscode-jsonrpc@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-3.6.0.tgz#848d56995d5168950d84feb5d9c237ae5c6a02d4"
vscode-languageclient@3.5.0, vscode-languageclient@^3.5.0:
vscode-languageclient@3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-3.5.0.tgz#36d02cc186a8365a4467719a290fb200a9ae490a"
dependencies:
vscode-languageserver-protocol "^3.5.0"
vscode-languageserver-protocol@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.0.tgz#067c5cbe27709795398d119692c97ebba1452209"
version "3.6.0"
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.6.0.tgz#579642cdcccf74b0cd771c33daa3239acb40d040"
dependencies:
vscode-jsonrpc "^3.5.0"
vscode-languageserver-types "^3.5.0"
vscode-jsonrpc "^3.6.0"
vscode-languageserver-types "^3.6.0"
vscode-languageserver-types@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0.tgz#e48d79962f0b8e02de955e3f524908e2b19c0374"
vscode-languageserver-types@^3.6.0:
version "3.6.1"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.6.1.tgz#4bc06a48dff653495f12f94b8b1e228988a1748d"
vscode@1.0.1:
version "1.0.1"

View File

@@ -29,7 +29,9 @@
"documentationUrl": "https://go.microsoft.com/fwlink/?linkid=862277",
"commit": "9ca6200018fc206d67a47229f991901a8a453781",
"date": "2017-12-15T12:00:00.000Z",
"recommendedExtensions": [],
"recommendedExtensions": [
"Microsoft.agent"
],
"extensionsGallery": {
"serviceUrl": "https://raw.githubusercontent.com/Microsoft/sqlopsstudio/release/extensions/extensionsGallery.json"
}

View File

@@ -0,0 +1,393 @@
// Adopted and converted to typescript from https://github.com/6pac/SlickGrid/blob/master/plugins/slick.rowdetailview.js
// heavily modified
import { mixin } from 'vs/base/common/objects';
export class RowDetailView {
public onAsyncResponse = new Slick.Event<any>();
public onAsyncEndUpdate = new Slick.Event<any>();
public onAfterRowDetailToggle = new Slick.Event<any>();
public onBeforeRowDetailToggle = new Slick.Event<any>();
private _grid: any;
private _expandedRows: any = [];
private _handler = new Slick.EventHandler();
private _defaults: any = {
columnId: '_detail_selector',
cssClass: null,
toolTip: '',
width: 30
};
private _dataView: any;
private _options: any;
constructor(options) {
this._options = mixin(options, this._defaults, false);
}
public init(grid: any) {
this._grid = grid;
this._dataView = this._grid.getData();
// Update the minRowBuffer so that the view doesn't disappear when it's at top of screen + the original default 3
this._grid.getOptions().minRowBuffer = this._options.panelRows + 3;
this._handler
.subscribe(this._grid.onClick, (e, args) => this.handleClick(e, args))
.subscribe(this._grid.onSort, (e, args) => this.handleSort(e, args))
.subscribe(this._grid.onScroll, (e, args) => this.handleScroll(e, args));
this._grid.getData().onRowCountChanged.subscribe(() => { this._grid.updateRowCount(); this._grid.render(); });
this._grid.getData().onRowsChanged.subscribe((e, a) => { this._grid.invalidateRows(a.rows); this._grid.render(); });
// subscribe to the onAsyncResponse so that the plugin knows when the user server side calls finished
this.subscribeToOnAsyncResponse();
}
public destroy() {
this._handler.unsubscribeAll();
this.onAsyncResponse.unsubscribe(undefined);
this.onAsyncEndUpdate.unsubscribe(undefined);
this.onAfterRowDetailToggle.unsubscribe(undefined);
this.onBeforeRowDetailToggle.unsubscribe(undefined);
}
public getOptions(options: any) {
return this._options;
}
public setOptions(options: any) {
this._options = $.extend(true, {}, this._options, options);
}
public handleClick(e: any, args: any) {
// clicking on a row select checkbox
if (this._options.useRowClick || this._grid.getColumns()[args.cell].id === this._options.columnId && $(e.target).hasClass("detailView-toggle")) {
// if editing, try to commit
if (this._grid.getEditorLock().isActive() && !this._grid.getEditorLock().commitCurrentEdit()) {
e.preventDefault();
e.stopImmediatePropagation();
return;
}
var item = this._dataView.getItem(args.row);
// trigger an event before toggling
this.onBeforeRowDetailToggle.notify({
grid: this._grid,
item: item
}, e, this);
this.toggleRowSelection(item);
// trigger an event after toggling
this.onAfterRowDetailToggle.notify({
grid: this._grid,
item: item
}, e, this);
e.stopPropagation();
e.stopImmediatePropagation();
}
}
// Sort will just collapse all of the open items
public handleSort(e, args) {
this.collapseAll();
}
// If we scroll save detail views that go out of cache range
public handleScroll(e, args) {
var range = this._grid.getRenderedRange();
var start = (range.top > 0 ? range.top : 0);
var end = (range.bottom > this._dataView.getLength() ? range.bottom : this._dataView.getLength());
// Get the item at the top of the view
var topMostItem = this._dataView.getItemByIdx(start);
// Check it is a parent item
if (topMostItem._parent === undefined)
{
// This is a standard row as we have no parent.
var nextItem = this._dataView.getItemByIdx(start + 1);
if(nextItem !== undefined && nextItem._parent !== undefined)
{
// This is likely the expanded Detail Row View
// Check for safety
if(nextItem._parent === topMostItem)
{
this.saveDetailView(topMostItem);
}
}
}
// Find the bottom most item that is likely to go off screen
var bottomMostItem = this._dataView.getItemByIdx(end - 1);
// If we are a detailView and we are about to go out of cache view
if(bottomMostItem._parent !== undefined)
{
this.saveDetailView(bottomMostItem._parent);
}
}
// Toggle between showing and hiding a row
public toggleRowSelection(row) {
this._grid.getData().beginUpdate();
this.handleAccordionShowHide(row);
this._grid.getData().endUpdate();
}
// Collapse all of the open items
public collapseAll() {
for (var i = this._expandedRows.length - 1; i >= 0; i--) {
this.collapseItem(this._expandedRows[i]);
}
}
// Saves the current state of the detail view
public saveDetailView(item) {
var view = $('#innerDetailView_' + item.id);
if (view) {
var html = $('#innerDetailView_' + item.id).html();
if(html !== undefined) {
item._detailContent = html;
}
}
}
// Colapse an Item so it is notlonger seen
public collapseItem(item) {
// Save the details on the collapse assuming onetime loading
if (this._options.loadOnce) {
this.saveDetailView(item);
}
item._collapsed = true;
for (let idx = 1; idx <= item._sizePadding; idx++) {
this._dataView.deleteItem(item.id + '.' + idx);
}
item._sizePadding = 0;
this._dataView.updateItem(item.id, item);
// Remove the item from the expandedRows
this._expandedRows = this._expandedRows.filter((r) => {
return r.id !== item.id;
});
}
// Expand a row given the dataview item that is to be expanded
public expandItem(item) {
item._collapsed = false;
this._expandedRows.push(item);
// In the case something went wrong loading it the first time such a scroll of screen before loaded
if (!item._detailContent) {
item._detailViewLoaded = false;
}
// display pre-loading template
if (!item._detailViewLoaded || this._options.loadOnce !== true) {
item._detailContent = this._options.preTemplate(item);
} else {
this.onAsyncResponse.notify({
itemDetail: item,
detailView: item._detailContent
}, undefined, this);
this.applyTemplateNewLineHeight(item);
this._dataView.updateItem(item.id, item);
return;
}
this.applyTemplateNewLineHeight(item);
this._dataView.updateItem(item.id, item);
// async server call
this._options.process(item);
}
/**
* subscribe to the onAsyncResponse so that the plugin knows when the user server side calls finished
* the response has to be as "args.itemDetail" with it's data back
*/
public subscribeToOnAsyncResponse() {
this.onAsyncResponse.subscribe((e, args) => {
if (!args || !args.itemDetail) {
throw 'Slick.RowDetailView plugin requires the onAsyncResponse() to supply "args.itemDetail" property.';
}
// If we just want to load in a view directly we can use detailView property to do so
if (args.detailView) {
args.itemDetail._detailContent = args.detailView;
} else {
args.itemDetail._detailContent = this._options.postTemplate(args.itemDetail);
}
args.itemDetail._detailViewLoaded = true;
var idxParent = this._dataView.getIdxById(args.itemDetail.id);
this._dataView.updateItem(args.itemDetail.id, args.itemDetail);
// trigger an event once the post template is finished loading
this.onAsyncEndUpdate.notify({
grid: this._grid,
itemDetail: args.itemDetail
}, e, this);
});
}
public handleAccordionShowHide(item) {
if (item) {
if (!item._collapsed) {
this.collapseItem(item);
} else {
this.expandItem(item);
}
}
}
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
public getPaddingItem(parent, offset) {
var item: any = {};
for (let prop in this._grid.getData()) {
item[prop] = null;
}
item.id = parent.id + '.' + offset;
//additional hidden padding metadata fields
item._collapsed = true;
item._isPadding = true;
item._parent = parent;
item._offset = offset;
return item;
}
//////////////////////////////////////////////////////////////
//create the detail ctr node. this belongs to the dev & can be custom-styled as per
//////////////////////////////////////////////////////////////
public applyTemplateNewLineHeight(item) {
// the height seems to be calculated by the template row count (how many line of items does the template have)
let rowCount = this._options.panelRows;
//calculate padding requirements based on detail-content..
//ie. worst-case: create an invisible dom node now &find it's height.
let lineHeight = 13; //we know cuz we wrote the custom css innit ;)
item._sizePadding = Math.ceil(((rowCount * 2) * lineHeight) / this._grid.getOptions().rowHeight);
item._height = (item._sizePadding * this._grid.getOptions().rowHeight);
let idxParent = this._dataView.getIdxById(item.id);
for (var idx = 1; idx <= item._sizePadding; idx++) {
this._dataView.insertItem(idxParent + idx, this.getPaddingItem(item, idx));
}
}
public getColumnDefinition() {
return {
id: this._options.columnId,
name: '',
toolTip: this._options.toolTip,
field: 'sel',
width: this._options.width,
resizable: false,
sortable: false,
cssClass: this._options.cssClass,
formatter: (row, cell, value, columnDef, dataContext) => this.detailSelectionFormatter(row, cell, value, columnDef, dataContext)
};
}
public detailSelectionFormatter(row, cell, value, columnDef, dataContext) {
if (dataContext._collapsed === undefined) {
dataContext._collapsed = true,
dataContext._sizePadding = 0, //the required number of pading rows
dataContext._height = 0, //the actual height in pixels of the detail field
dataContext._isPadding = false,
dataContext._parent = undefined,
dataContext._offset = 0
}
if (dataContext._isPadding === true) {
//render nothing
} else if (dataContext._collapsed) {
return '<div class=\'detailView-toggle expand\'></div>';
} else {
var html = [];
var rowHeight = this._grid.getOptions().rowHeight;
var bottomMargin = 5;
//V313HAX:
//putting in an extra closing div after the closing toggle div and ommiting a
//final closing div for the detail ctr div causes the slickgrid renderer to
//insert our detail div as a new column ;) ~since it wraps whatever we provide
//in a generic div column container. so our detail becomes a child directly of
//the row not the cell. nice =) ~no need to apply a css change to the parent
//slick-cell to escape the cell overflow clipping.
//sneaky extra </div> inserted here-----------------v
html.push("<div class='detailView-toggle collapse'></div></div>");
html.push("<div id='cellDetailView_", dataContext.id, "' class='dynamic-cell-detail' "); //apply custom css to detail
html.push("style='height:", dataContext._height, "px;"); //set total height of padding
html.push("top:", rowHeight, "px'>"); //shift detail below 1st row
html.push("<div id='detailViewContainer_", dataContext.id, "' class='detail-container' style='max-height:" + (dataContext._height - rowHeight + bottomMargin) + "px'>"); //sub ctr for custom styling
html.push("<div id='innerDetailView_" , dataContext.id , "'>" , dataContext._detailContent, "</div></div>");
//&omit a final closing detail container </div> that would come next
return html.join('');
}
return null;
}
public resizeDetailView(item) {
if (!item) return;
// Grad each of the dom items
var mainContainer = document.getElementById('detailViewContainer_' + item.id);
var cellItem = document.getElementById('cellDetailView_' + item.id);
var inner = document.getElementById('innerDetailView_' + item.id);
if (!mainContainer || !cellItem || !inner) return;
for (var idx = 1; idx <= item._sizePadding; idx++) {
this._dataView.deleteItem(item.id + "." + idx);
}
var rowHeight = this._grid.getOptions().rowHeight; // height of a row
var lineHeight = 13; //we know cuz we wrote the custom css innit ;)
// Get the inner Item height as this will be the actual size
var itemHeight = inner.clientHeight;
// Now work out how many rows
var rowCount = Math.ceil(itemHeight / rowHeight) + 1;
item._sizePadding = Math.ceil(((rowCount * 2) * lineHeight) / rowHeight);
item._height = (item._sizePadding * rowHeight);
// If the padding is now more than the original minRowBuff we need to increase it
if (this._grid.getOptions().minRowBuffer < item._sizePadding)
{
// Update the minRowBuffer so that the view doesn't disappear when it's at top of screen + the original default 3
this._grid.getOptions().minRowBuffer =item._sizePadding + 3;
}
mainContainer.setAttribute("style", "max-height: " + item._height + "px");
if (cellItem) {
cellItem.setAttribute("style", "height: " + item._height + "px;top:" + rowHeight + "px");
}
let idxParent = this._dataView.getIdxById(item.id);
for (var idx = 1; idx <= item._sizePadding; idx++) {
this._dataView.insertItem(idxParent + idx, this.getPaddingItem(item, idx));
}
}
}

View File

@@ -16,6 +16,7 @@ import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboar
import { WIDGETS_CONTAINER } from 'sql/parts/dashboard/containers/dashboardWidgetContainer.contribution';
import { GRID_CONTAINER } from 'sql/parts/dashboard/containers/dashboardGridContainer.contribution';
import { WEBVIEW_CONTAINER } from 'sql/parts/dashboard/containers/dashboardWebviewContainer.contribution';
import { CONTROLHOST_CONTAINER } from 'sql/parts/dashboard/containers/dashboardControlHostContainer.contribution';
import { NAV_SECTION } from 'sql/parts/dashboard/containers/dashboardNavSection.contribution';
import { IDashboardContainerRegistry, Extensions as DashboardContainerExtensions, IDashboardContainer, registerContainerType } from 'sql/platform/dashboard/common/dashboardContainerRegistry';
import { IDashboardTab } from 'sql/platform/dashboard/common/dashboardRegistry';
@@ -26,6 +27,7 @@ const containerTypes = [
WIDGETS_CONTAINER,
GRID_CONTAINER,
WEBVIEW_CONTAINER,
CONTROLHOST_CONTAINER,
NAV_SECTION
];

View File

@@ -13,6 +13,8 @@
</dashboard-webview-container>
<dashboard-widget-container *ngIf="getContentType(tab) === 'widgets-container'" [tab]="tab">
</dashboard-widget-container>
<dashboard-controlhost-container *ngIf="getContentType(tab) === 'controlhost-container'" [tab]="tab">
</dashboard-controlhost-container>
<dashboard-nav-section *ngIf="getContentType(tab) === 'nav-section'" [tab]="tab">
</dashboard-nav-section>
<dashboard-grid-container *ngIf="getContentType(tab) === 'grid-container'" [tab]="tab">

View File

@@ -0,0 +1,58 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./dashboardControlHostContainer';
import { Component, forwardRef, Input, AfterContentInit, ViewChild } from '@angular/core';
import Event, { Emitter } from 'vs/base/common/event';
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
import { ControlHostContent } from 'sql/parts/dashboard/contents/controlHostContent.component';
@Component({
selector: 'dashboard-controlhost-container',
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardControlHostContainer) }],
template: `
<controlhost-content [webviewId]="tab.id">
</controlhost-content>
`
})
export class DashboardControlHostContainer extends DashboardTab implements AfterContentInit {
@Input() private tab: TabConfig;
private _onResize = new Emitter<void>();
public readonly onResize: Event<void> = this._onResize.event;
@ViewChild(ControlHostContent) private _hostContent: ControlHostContent;
constructor() {
super();
}
ngAfterContentInit(): void {
this._register(this._hostContent.onResize(() => {
this._onResize.fire();
}));
let container = <any>this.tab.container;
if (container['controlhost-container'] && container['controlhost-container'].type) {
this._hostContent.setControlType(container['controlhost-container'].type);
}
}
public layout(): void {
this._hostContent.layout();
}
public get id(): string {
return this.tab.id;
}
public get editable(): boolean {
return this.tab.editable;
}
public refresh(): void {
// no op
}
}

View File

@@ -0,0 +1,19 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IJSONSchema } from 'vs/base/common/jsonSchema';
import * as nls from 'vs/nls';
import { registerContainerType, registerNavSectionContainerType } from 'sql/platform/dashboard/common/dashboardContainerRegistry';
export const CONTROLHOST_CONTAINER = 'controlhost-container';
let webviewSchema: IJSONSchema = {
type: 'null',
description: nls.localize('dashboard.container.controlhost', "The controlhost that will be displayed in this tab."),
default: null
};
registerContainerType(CONTROLHOST_CONTAINER, webviewSchema);
registerNavSectionContainerType(CONTROLHOST_CONTAINER, webviewSchema);

View File

@@ -0,0 +1,10 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
dashboard-controlhost-container {
height: 100%;
width : 100%;
display: block;
}

View 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.
*--------------------------------------------------------------------------------------------*/
-->
<agentview-component *ngIf="(controlType) === 'agent'">
</agentview-component>

View File

@@ -0,0 +1,76 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./controlHostContent';
import { Component, forwardRef, Input, OnInit, Inject, ChangeDetectorRef, ElementRef } from '@angular/core';
import Event, { Emitter } from 'vs/base/common/event';
import { Parts } from 'vs/workbench/services/part/common/partService';
import { IDisposable } from 'vs/base/common/lifecycle';
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
import * as sqlops from 'sqlops';
import { memoize } from 'vs/base/common/decorators';
@Component({
templateUrl: decodeURI(require.toUrl('sql/parts/dashboard/contents/controlHostContent.component.html')),
selector: 'controlhost-content'
})
export class ControlHostContent implements OnInit {
@Input() private webviewId: string;
private _onResize = new Emitter<void>();
public readonly onResize: Event<void> = this._onResize.event;
private _onMessage = new Emitter<string>();
public readonly onMessage: Event<string> = this._onMessage.event;
private _onMessageDisposable: IDisposable;
private _type: string;
constructor(
@Inject(forwardRef(() => DashboardServiceInterface)) private _dashboardService: DashboardServiceInterface,
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeRef: ChangeDetectorRef,
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef
) {
}
ngOnInit() {
}
public layout(): void {
}
public get id(): string {
return this.webviewId;
}
@memoize
public get connection(): sqlops.connection.Connection {
let currentConnection = this._dashboardService.connectionManagementService.connectionInfo.connectionProfile;
let connection: sqlops.connection.Connection = {
providerName: currentConnection.providerName,
connectionId: currentConnection.id,
options: currentConnection.options
};
return connection;
}
@memoize
public get serverInfo(): sqlops.ServerInfo {
return this._dashboardService.connectionManagementService.connectionInfo.serverInfo;
}
public setControlType(type: string): void {
this._type = type;
this._changeRef.detectChanges();
}
public get controlType(): string {
return this._type;
}
}

View File

@@ -0,0 +1,10 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
controlhost-content {
height: 100%;
width : 100%;
display: block;
}

View File

@@ -42,8 +42,16 @@ import { WebviewContent } from 'sql/parts/dashboard/contents/webviewContent.comp
import { BreadcrumbComponent } from 'sql/base/browser/ui/breadcrumb/breadcrumb.component';
import { IBreadcrumbService } from 'sql/base/browser/ui/breadcrumb/interfaces';
import { DashboardHomeContainer } from 'sql/parts/dashboard/containers/dashboardHomeContainer.component';
import { ControlHostContent } from 'sql/parts/dashboard/contents/controlHostContent.component';
import { DashboardControlHostContainer } from 'sql/parts/dashboard/containers/dashboardControlHostContainer.component';
import { JobsViewComponent } from 'sql/parts/jobManagement/views/jobsView.component';
import { AgentViewComponent } from 'sql/parts/jobManagement/agent/agentView.component';
import { JobHistoryComponent } from 'sql/parts/jobManagement/views/jobHistory.component';
let baseComponents = [DashboardHomeContainer, DashboardComponent, DashboardWidgetWrapper, DashboardWebviewContainer, DashboardWidgetContainer, DashboardGridContainer, DashboardErrorContainer, DashboardNavSection, WidgetContent, WebviewContent, ComponentHostDirective, BreadcrumbComponent];
let baseComponents = [DashboardHomeContainer, DashboardComponent, DashboardWidgetWrapper, DashboardWebviewContainer,
DashboardWidgetContainer, DashboardGridContainer, DashboardErrorContainer, DashboardNavSection, WebviewContent, WidgetContent,
ComponentHostDirective, BreadcrumbComponent, ControlHostContent, DashboardControlHostContainer,
JobsViewComponent, AgentViewComponent, JobHistoryComponent];
/* Panel */
import { PanelModule } from 'sql/base/browser/ui/panel/panel.module';

View File

@@ -0,0 +1,18 @@
<!--
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-->
<panel class="fullsize" [options]="panelOpt">
<tab [title]="jobsComponentTitle" class="fullsize" [identifier]="jobsTabIdentifier"
[iconClass]="jobsIconClass">
<div id="jobsDiv" class="fullsize" *ngIf="showHistory === false">
<jobsview-component ></jobsview-component>
</div>
<div id="historyDiv" class="fullsize" *ngIf="showHistory === true">
<jobhistory-component [jobId]="jobId" [agentJobInfo]="agentJobInfo"></jobhistory-component>
</div>
</tab>
</panel>

View 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.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!../common/media/jobs';
import { OnInit, Component, Inject, forwardRef, ElementRef, ChangeDetectorRef, OnDestroy, ViewChild, Injectable } from '@angular/core';
import * as Utils from 'sql/parts/connection/common/utils';
import { RefreshWidgetAction, EditDashboardAction } from 'sql/parts/dashboard/common/actions';
import { IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IDisposable } from 'vs/base/common/lifecycle';
import * as themeColors from 'vs/workbench/common/theme';
import { DashboardPage } from 'sql/parts/dashboard/common/dashboardPage.component';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { IBootstrapService, BOOTSTRAP_SERVICE_ID } from 'sql/services/bootstrap/bootstrapService';
import { IJobManagementService } from '../common/interfaces';
import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
import { AgentJobInfo, AgentJobHistoryInfo } from 'sqlops';
import { PanelComponent, IPanelOptions, NavigationBarLayout } from 'sql/base/browser/ui/panel/panel.component';
import * as nls from 'vs/nls';
export const DASHBOARD_SELECTOR: string = 'agentview-component';
@Component({
selector: DASHBOARD_SELECTOR,
templateUrl: decodeURI(require.toUrl('./agentView.component.html'))
})
@Injectable()
export class AgentViewComponent {
@ViewChild(PanelComponent) private _panel: PanelComponent;
// tslint:disable:no-unused-variable
private readonly jobsComponentTitle: string = nls.localize('jobview.Jobs', "Jobs");
private readonly alertsComponentTitle: string = nls.localize('jobview.Alerts', "Alerts");
private readonly schedulesComponentTitle: string = nls.localize('jobview.Schedules', "Schedules");
private readonly operatorsComponentTitle: string = nls.localize('jobview.Operator', "Operators");
private readonly jobHistoryComponentTitle: string = nls.localize('jobview.History', "History");
private _showHistory: boolean = false;
private _jobId: string = null;
private _agentJobInfo: AgentJobInfo = null;
private _agentJobHistoryInfo: AgentJobHistoryInfo[] = null;
public jobsIconClass: string = 'jobsview-icon';
// tslint:disable-next-line:no-unused-variable
private readonly panelOpt: IPanelOptions = {
showTabsWhenOne: true,
layout: NavigationBarLayout.vertical,
showIcon: true
};
constructor(
@Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef,
){}
/**
* Public Getters
*/
public get jobId(): string {
return this._jobId;
}
public get showHistory(): boolean {
return this._showHistory;
}
public get agentJobInfo(): AgentJobInfo {
return this._agentJobInfo;
}
public get agentJobHistoryInfo(): AgentJobHistoryInfo[] {
return this._agentJobHistoryInfo;
}
/**
* Public Setters
*/
public set jobId(value: string) {
this._jobId = value;
this._cd.detectChanges();
}
public set showHistory(value: boolean) {
this._showHistory = value;
this._cd.detectChanges();
}
public set agentJobInfo(value: AgentJobInfo) {
this._agentJobInfo = value;
this._cd.detectChanges();
}
public set agentJobHistoryInfo(value: AgentJobHistoryInfo[]) {
this._agentJobHistoryInfo = value;
this._cd.detectChanges();
}
}

View File

@@ -0,0 +1,25 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import * as sqlops from 'sqlops';
export const SERVICE_ID = 'jobManagementService';
export const IJobManagementService = createDecorator<IJobManagementService>(SERVICE_ID);
export interface IJobManagementService {
_serviceBrand: any;
registerProvider(providerId: string, provider: sqlops.AgentServicesProvider): void;
getJobs(connectionUri: string): Thenable<sqlops.AgentJobsResult>;
getJobHistory(connectionUri: string, jobID: string): Thenable<sqlops.AgentJobHistoryResult>;
jobAction(connectionUri: string, jobName: string, action: string): Thenable<sqlops.AgentJobActionResult>;
}

View File

@@ -0,0 +1,63 @@
/*---------------------------------------------------------------------------------------------
* 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 { localize } from 'vs/nls';
import { IJobManagementService } from 'sql/parts/jobManagement/common/interfaces';
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
import { TPromise } from 'vs/base/common/winjs.base';
import * as sqlops from 'sqlops';
export class JobManagementService implements IJobManagementService {
_serviceBrand: any;
private _providers: { [handle: string]: sqlops.AgentServicesProvider; } = Object.create(null);
constructor(
@IConnectionManagementService private _connectionService: IConnectionManagementService,
@ICapabilitiesService private _capabilitiesService: ICapabilitiesService
) {
}
public getJobs(connectionUri: string): Thenable<sqlops.AgentJobsResult> {
return this._runAction(connectionUri, (runner) => {
return runner.getJobs(connectionUri);
});
}
public getJobHistory(connectionUri: string, jobID: string): Thenable<sqlops.AgentJobHistoryResult> {
return this._runAction(connectionUri, (runner) => {
return runner.getJobHistory(connectionUri, jobID);
});
}
public jobAction(connectionUri: string, jobName: string, action: string): Thenable<sqlops.AgentJobActionResult> {
return this._runAction(connectionUri, (runner) => {
return runner.jobAction(connectionUri, jobName, action);
});
}
private _runAction<T>(uri: string, action: (handler: sqlops.AgentServicesProvider) => Thenable<T>): Thenable<T> {
let providerId: string = this._connectionService.getProviderIdFromUri(uri);
if (!providerId) {
return TPromise.wrapError(new Error(localize('providerIdNotValidError', "Connection is required in order to interact with JobManagementService")));
}
let handler = this._providers[providerId];
if (handler) {
return action(handler);
} else {
return TPromise.wrapError(new Error(localize('noHandlerRegistered', "No Handler Registered")));
}
}
public registerProvider(providerId: string, provider: sqlops.AgentServicesProvider): void {
this._providers[providerId] = provider;
}
}

View 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:#212121;}</style></defs><title>back_16x16</title><path class="cls-1" d="M16.15,8.5H2.1l6.15,6.15-.7.7L.19,8,7.55.65l.7.7L2.1,7.5h14Z"/></svg>

After

Width:  |  Height:  |  Size: 259 B

View 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;}</style></defs><title>back_inverse_16x16</title><path class="cls-1" d="M16.15,8.5H2.1l6.15,6.15-.7.7L.19,8,7.55.65l.7.7L2.1,7.5h14Z"/></svg>

After

Width:  |  Height:  |  Size: 264 B

View File

@@ -0,0 +1,39 @@
.detailView-toggle
{
display: inline-block;
cursor: pointer;
}
.detailView-toggle.expand
{
height: 20px;
width: 20px;
background: url(../images/arrow-right.gif) no-repeat center center;
}
.detailView-toggle.collapse
{
height: 20px;
width: 20px;
background: url(../images/sort-desc.gif) no-repeat center center;
}
.dynamic-cell-detail
{
z-index: 10000;
position: absolute;
background-color: #dae5e8;
margin: 0;
padding: 0;
width: 100%;
overflow: auto;
}
.dynamic-cell-detail > :first-child
{
vertical-align: middle;
line-height: 13px;
}
.dynamic-cell-detail > .detail-container {
overflow: auto;
display: block !important;
}

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>job</title><path d="M11,4h5v9H0V4H5V2h6Zm4,1H1V7H4V6H5V7h6V6h1V7h3ZM1,12H15V8H12V9H11V8H5V9H4V8H1ZM6,3V4h4V3Z"/></svg>

After

Width:  |  Height:  |  Size: 218 B

View 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;}</style></defs><title>job_inverse</title><path class="cls-1" d="M11,4h5v9H0V4H5V2h6Zm4,1H1V7H4V6H5V7h6V6h1V7h3ZM1,12H15V8H12V9H11V8H5V9H4V8H1ZM6,3V4h4V3Z"/></svg>

After

Width:  |  Height:  |  Size: 286 B

View File

@@ -0,0 +1,134 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
agentview-component {
height: 100%;
width : 100%;
display: block;
}
jobsview-component {
height: 100%;
width : 100%;
display: block;
}
jobhistory-component {
height: 100%;
width : 100%;
display: block;
}
#jobsDiv .jobview-grid {
height: 100%;
width : 100%;
display: block;
}
.vs-dark #jobsDiv .slick-header-column {
background: #333333 !important;
}
#jobsDiv .slick-header-column {
background-color: transparent !important;
background: white !important;
border: 0px !important;
font-weight: bold;
font-size: larger;
}
.vs-dark #jobsDiv .slick-cell {
background:#333333 !important;
}
#jobsDiv .slick-cell {
background: white !important;
border-right: transparent !important;
border-left: transparent !important;
line-height: 33px !important;
vertical-align: middle;
}
#jobsDiv .jobview-joblist {
height: 100%;
width: 100%;
}
#jobsDiv .jobview-jobnametable {
border: 0px;
width: 100%;
height: 100%;
}
#jobsDiv .jobview-jobnameindicatorsuccess {
width: 5px;
background: green;
}
#jobsDiv .jobview-jobnametext {
width: 100%;
}
#jobsDiv .jobview-splitter {
height: 1px;
width: 100%;
background-color: gray;
}
#jobsDiv .jobview-jobitem {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
flex-flow: row wrap;
white-space: nowrap;
}
#jobsDiv .jobview-label {
padding-bottom: 10px;
padding-top: 10px;
}
#jobsDiv .jobview-highlight-none {
width: 5px;
margin-right: 10px;
}
#jobsDiv .detail-container {
max-height: 100px !important;
line-height: 20px;
}
#jobsDiv .detail {
padding: 5px
}
#jobsDiv .preload {
font-size: 18px;
}
#jobsDiv .dynamic-cell-detail > :first-child {
vertical-align: middle;
line-height: 13px;
padding: 10px;
margin-left: 20px;
}
.vs-dark #jobsDiv .dynamic-cell-detail {
background: black !important;
}
#jobsDiv .dynamic-cell-detail {
background: #faf5f8 !important;
}
.jobsview-icon {
content: url('./job.svg');
width: 25px;
}
.vs-dark .jobsview-icon {
content: url('./job_inverse.svg');
}

View 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:#3bb44a;}</style></defs><title>run</title><path class="cls-1" d="M3.24,0,14.61,8,3.24,16Zm2,12.07L11.13,8,5.24,3.88Z"/><path class="cls-1" d="M3.74,1l10,7-10,7Zm1,1.92V13.07L12,8Z"/></svg>

After

Width:  |  Height:  |  Size: 306 B

View 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:#d02e00;}</style></defs><title>stop</title><path class="cls-1" d="M.5,15.3V.3h15v15Zm13-2V2.3H2.5v11Z"/><path class="cls-1" d="M1,.8H15v14H1Zm13,13V1.8H2v12Z"/></svg>

After

Width:  |  Height:  |  Size: 284 B

View File

@@ -0,0 +1,155 @@
<!--
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-->
<h1 class="job-heading">Jobs | {{agentJobInfo.name}} </h1>
<!-- Back -->
<div class="all-jobs">
<div class="back-button-icon" (click)="goToJobs()"></div>All Jobs
</div>
<!-- Actions -->
<ul class="action-buttons">
<li>
<div class="icon-start" (click)="jobAction('start')">Run</div>
</li>
<li>
<div class="icon-stop" (click)="jobAction('stop')">Stop</div>
</li>
</ul>
<!-- Overview -->
<div class="overview-container">
<div class="overview-tab" (click)='toggleCollapse()'>
<input id="accordion" type="checkbox">
<label for="accordion">
<div class="resultsViewCollapsible collapsed" (click)='toggleCollapse()'></div>
Overview
</label>
<div class="accordion-content">
<table align='left'>
<tr>
<td id='col1'>
User:
</td>
<td id='col2'>
</td>
<td id='col3'>
Enabled:
</td>
<td id='col4'>
{{agentJobInfo.enabled}}
</td>
</tr>
<tr>
<td id='col1'>
Alert:
</td>
<td id='col2'>
</td>
<td id='col3'>
Notification:
</td>
<td id='col4'>
</td>
</tr>
<tr>
<td id='col1'>
Schedule:
</td>
<td id='col2'>
</td>
<td id='col3'>
Target Server:
</td>
<td id='col4'>
</td>
</tr>
</table>
</div>
</div>
</div>
<!-- Job History details -->
<div class='history-details'>
<!-- Previous run list -->
<div style="width: 20%">
<table>
<tr>
<td class="date-column">
<b>Date</b>
</td>
<td>
<b>Status</b>
</td>
</tr>
</table>
<div #table class="step-table prev-run-list" style="position: relative; height: 100%; width: 100%"></div>
</div>
<!-- Job Steps -->
<div class="job-steps">
<h1 class="job-heading">
{{agentJobInfo.lastRun}}
</h1>
<table class="step-list">
<tr class="step-row">
<td height="30">
<h3>Status:</h3>
</td>
<td>
<h3></h3>
</td>
</tr>
<tr class="step-row">
<td height="30">
Error Message:
</td>
<td>
</td>
</tr>
<tr class="step-row">
<td height="30">
Duration:
</td>
<td>
</td>
</tr>
<tr class="step-row">
<td height="30">
Log:
</td>
<td>
</td>
</tr>
<tr class="step-row">
<td height="30">
SQL message ID:
</td>
<td>
</td>
</tr>
<tr class="step-row">
<td height="30">
Retries Attempted:
</td>
<td>
</td>
</tr>
</table>
</div>
</div>

View File

@@ -0,0 +1,132 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./jobHistory';
import { OnInit, Component, Inject, forwardRef, ElementRef, ChangeDetectorRef, OnDestroy, ViewChild, Input } from '@angular/core';
import { ICancelableEvent } from 'vs/base/parts/tree/browser/treeDefaults';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { attachListStyler } from 'vs/platform/theme/common/styler';
import { getContentHeight } from 'vs/base/browser/dom';
import { Tree } from 'vs/base/parts/tree/browser/treeImpl';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { PanelComponent } from 'sql/base/browser/ui/panel/panel.component';
import { IBootstrapService, BOOTSTRAP_SERVICE_ID } from 'sql/services/bootstrap/bootstrapService';
import { IJobManagementService } from '../common/interfaces';
import { ExplorerDataSource } from 'sql/parts/dashboard/widgets/explorer/explorerTree';
import { TreeCreationUtils } from 'sql/parts/registeredServer/viewlet/treeCreationUtils';
import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
import { AgentViewComponent } from 'sql/parts/jobManagement/agent/agentView.component';
import { JobHistoryController, JobHistoryDataSource,
JobHistoryRenderer, JobHistoryFilter, JobHistoryModel, JobHistoryRow } from 'sql/parts/jobManagement/views/jobHistoryTree';
import { AgentJobHistoryInfo, AgentJobInfo } from 'sqlops';
import { toDisposableSubscription } from '../../common/rxjsUtils';
export const DASHBOARD_SELECTOR: string = 'jobhistory-component';
@Component({
selector: DASHBOARD_SELECTOR,
templateUrl: decodeURI(require.toUrl('./jobHistory.component.html'))
})
export class JobHistoryComponent extends Disposable implements OnInit, OnDestroy {
private _jobManagementService: IJobManagementService;
private _tree: Tree;
private _treeController = new JobHistoryController();
private _treeDataSource = new JobHistoryDataSource();
private _treeRenderer = new JobHistoryRenderer();
private _treeFilter = new JobHistoryFilter();
@ViewChild('table') private _tableContainer: ElementRef;
@Input() public agentJobInfo: AgentJobInfo = undefined;
@Input() public jobId: string = undefined;
@Input() public agentJobHistoryInfo: AgentJobHistoryInfo = undefined;
private prevJobId: string = undefined;
private jobName: string = undefined;
private isVisible: boolean = false;
constructor(
@Inject(BOOTSTRAP_SERVICE_ID) private bootstrapService: IBootstrapService,
@Inject(forwardRef(() => ElementRef)) el: ElementRef,
@Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef,
@Inject(forwardRef(() => DashboardServiceInterface)) private _dashboardService: DashboardServiceInterface,
@Inject(forwardRef(() => AgentViewComponent)) private _agentViewComponent: AgentViewComponent
) {
super();
this._jobManagementService = bootstrapService.jobManagementService;
}
ngOnInit() {
let ownerUri: string = this._dashboardService.connectionManagementService.connectionInfo.ownerUri;
this.loadHistory();
this._treeDataSource.data = [];
this._tree = new Tree(this._tableContainer.nativeElement, {
controller: this._treeController,
dataSource: this._treeDataSource,
filter: this._treeFilter,
renderer: this._treeRenderer
});
this._register(attachListStyler(this._tree, this.bootstrapService.themeService));
this._tree.layout(1024);
//this._tree.setInput(new JobHistoryModel());
}
ngOnDestroy() {
}
ngAfterContentChecked() {
if (this.isVisible === false && this._tableContainer.nativeElement.offsetParent !== null) {
if (this.prevJobId !== undefined && this.prevJobId !== this.jobId) {
this.loadHistory();
this.prevJobId = this.jobId;
}
}
}
loadHistory() {
let ownerUri: string = this._dashboardService.connectionManagementService.connectionInfo.ownerUri;
this._jobManagementService.getJobHistory(ownerUri, this.jobId).then((result) => {
if (result.jobs) {
let jobHistory = result.jobs;
this._treeDataSource.data = jobHistory.map(job => this.convertToJobHistoryRow(job));
this._tree.setInput(new JobHistoryModel());
}
});
}
private toggleCollapse(): void {
let arrow: HTMLElement = $('.resultsViewCollapsible').get(0);
let checkbox: any = document.getElementById('accordion');
if (arrow.className === 'resultsViewCollapsible' && checkbox.checked === false) {
arrow.className = 'resultsViewCollapsible collapsed';
} else if (arrow.className === 'resultsViewCollapsible collapsed' && checkbox.checked === true) {
arrow.className = 'resultsViewCollapsible';
}
}
private jobAction(action: string): void {
let ownerUri: string = this._dashboardService.connectionManagementService.connectionInfo.ownerUri;
this._jobManagementService.jobAction(ownerUri, 'jobName', action);
}
private goToJobs(): void {
this._agentViewComponent.showHistory = false;
}
private convertToJobHistoryRow(historyInfo: AgentJobHistoryInfo): JobHistoryRow {
let jobHistoryRow = {
runDate: historyInfo.runDate,
runStatus: JobHistoryRow.convertToStatusString(historyInfo.runStatus),
jobID: historyInfo.jobID
};
return jobHistoryRow;
}
}

View File

@@ -0,0 +1,221 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.all-jobs {
display: inline;
font-size: 15px;
padding-bottom: 15px;
}
.vs-dark ul.action-buttons {
border-top: 3px solid #444444;
}
.action-buttons {
padding-top: 15px;
padding-left: 10px;
border-top: 3px solid #f4f4f4;
list-style-type: none;
}
ul.action-buttons .icon-start, .icon-stop {
padding-left: 25px;
}
ul.action-buttons li {
padding-right: 25px;
display: inline-block;
width: 50px;
cursor: pointer;
}
.overview-container .overview-tab .resultsViewCollapsible {
padding: 15px;
display: inline;
}
.job-heading {
text-align: left;
padding-left: 13px;
}
.vs-dark .overview-container .overview-tab {
color: #fff;
}
.overview-container > .overview-tab {
position: relative;
margin-bottom: 1px;
width: 100%;
color: #4a4a4a;
overflow: hidden;
}
input#accordion {
position: absolute;
opacity: 0;
z-index: -1;
}
.vs-dark .overview-container .overview-tab label {
background: #444444;
}
.overview-container .overview-tab label {
position: relative;
display: block;
padding: 0 0 0 1em;
background: #f4f4f4;
font-weight: bold;
line-height: 3;
cursor: pointer;
width: 100%;
}
.vs-dark .overview-tab .accordion-content {
background: #333333;
}
.overview-tab .accordion-content {
max-height: 0;
overflow: hidden;
background: #eaeaea;
-webkit-transition: max-height .35s;
-o-transition: max-height .35s;
transition: max-height .35s;
width: 100%;
}
.overview-tab .accordion-content p {
margin: 1em;
}
/* :checked */
input#accordion:checked ~ .accordion-content {
max-height: 10em;
}
/* Icon */
.overview-container .overview-tab label::after {
position: absolute;
right: 0;
top: 0;
display: block;
width: 3em;
height: 3em;
line-height: 3;
text-align: center;
-webkit-transition: all .3s;
-o-transition: all .3s;
transition: all .3s;
}
.all-jobs > .back-button-icon {
content: url('../common/media/back.svg');
width: 20px;
margin-right: 10px;
float: left;
cursor: pointer;
padding-left: 13px;
}
.vs-dark.monaco-shell .all-jobs >.back-button-icon {
content: url('../common/media/back_inverse.svg');
}
.vs ul.action-buttons div.icon-start,
.vs-dark ul.action-buttons div.icon-start,
.hc-black ul.action-buttons div.icon-start {
display: inline-block;
height: 20px;
width: 20px;
background-image: url('../common/media/start.svg');
background-repeat: no-repeat;
}
.vs ul.action-buttons .icon-stop,
.vs-dark ul.action-buttons .icon-stop,
.hc-black ul.action-buttons .icon-stop {
display: inline-block;
background-image: url('../common/media/stop.svg');
background-repeat: no-repeat;
height: 20px;
width: 20px;
}
.accordion-content #col1,
.accordion-content #col2,
.accordion-content #col3,
.accordion-content #col4 {
padding: 10px;
}
.accordion-content #col2 {
padding-right: 300px;
}
table.step-list tr.step-row td {
padding-right: 100px;
}
.history-details {
height: 100%;
display: flex;
}
.vs-dark .history-details > .job-steps {
display: inline-block;
border-left: 3px solid #444444;
padding-left: 10px;
height: 100%;
}
.history-details > .job-steps {
display: inline-block;
border-left: 3px solid #f4f4f4;
padding-left: 10px;
height: 100%;
}
.vs-dark .step-table .monaco-tree .monaco-tree-rows.show-twisties > .monaco-tree-row.has-children > .content:before {
background-image: none;
}
.step-table .monaco-tree .monaco-tree-rows.show-twisties > .monaco-tree-row.has-children > .content:before {
background: none;
}
.step-table .monaco-tree.focused .monaco-tree-rows.show-twisties > .monaco-tree-row.has-children.selected:not(.loading) > .content:before {
background-image: none;
}
.step-table .list-row .status-icon {
height: 10px;
width: 10px;
display: inline-block;
}
.step-table .list-row .label {
padding-left: 10px;
display: inline-block;
}
.passed {
background: green;
}
.failed {
background: red;
}
.unknown {
background: yellow;
}
.date-column {
padding-left: 50px;
width: 140px;
}

View 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.
*--------------------------------------------------------------------------------------------*/
import { Router } from '@angular/router';
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
import { MetadataType } from 'sql/parts/connection/common/connectionManagement';
import { SingleConnectionManagementService } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
import {
NewQueryAction, ScriptSelectAction, EditDataAction, ScriptCreateAction, ScriptExecuteAction, ScriptAlterAction,
BackupAction, ManageActionContext, BaseActionContext, ManageAction, RestoreAction
} from 'sql/workbench/common/actions';
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
import { ConnectionManagementInfo } from 'sql/parts/connection/common/connectionManagementInfo';
import * as Constants from 'sql/parts/connection/common/constants';
import * as tree from 'vs/base/parts/tree/browser/tree';
import * as TreeDefaults from 'vs/base/parts/tree/browser/treeDefaults';
import { Promise, TPromise } from 'vs/base/common/winjs.base';
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IAction } from 'vs/base/common/actions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { generateUuid } from 'vs/base/common/uuid';
import * as DOM from 'vs/base/browser/dom';
import { OEAction } from 'sql/parts/registeredServer/viewlet/objectExplorerActions';
import { Builder, $, withElementById } from 'vs/base/browser/builder';
export class JobHistoryRow {
runDate: string;
runStatus: string;
jobID: string;
public static convertToStatusString(status: number): string {
switch(status) {
case(1): return 'Succeeded';
case(0): return 'Failed';
default: return 'Unknown';
}
}
}
// Empty class just for tree input
export class JobHistoryModel {
public static readonly id = generateUuid();
}
export class JobHistoryController extends TreeDefaults.DefaultController {
protected onLeftClick(tree: tree.ITree, element: JobHistoryRow, event: IMouseEvent, origin: string = 'mouse'): boolean {
const payload = { origin: origin };
const isDoubleClick = (origin === 'mouse' && event.detail === 2);
// Cancel Event
const isMouseDown = event && event.browserEvent && event.browserEvent.type === 'mousedown';
if (!isMouseDown) {
event.preventDefault(); // we cannot preventDefault onMouseDown because this would break DND otherwise
}
event.stopPropagation();
tree.setFocus(element, payload);
if (element && isDoubleClick) {
event.preventDefault(); // focus moves to editor, we need to prevent default
} else {
tree.setFocus(element, payload);
tree.setSelection([element], payload);
}
return true;
}
public onContextMenu(tree: tree.ITree, element: JobHistoryRow, event: tree.ContextMenuEvent): boolean {
return true;
}
}
export class JobHistoryDataSource implements tree.IDataSource {
private _data: JobHistoryRow[];
public getId(tree: tree.ITree, element: JobHistoryRow | JobHistoryModel): string {
if (element instanceof JobHistoryModel) {
return JobHistoryModel.id;
} else {
return (element as JobHistoryRow).jobID;
}
}
public hasChildren(tree: tree.ITree, element: JobHistoryRow | JobHistoryModel): boolean {
if (element instanceof JobHistoryModel) {
return true;
} else {
return false;
}
}
public getChildren(tree: tree.ITree, element: JobHistoryRow | JobHistoryModel): Promise {
if (element instanceof JobHistoryModel) {
return TPromise.as(this._data);
} else {
return TPromise.as(undefined);
}
}
public getParent(tree: tree.ITree, element: JobHistoryRow | JobHistoryModel): Promise {
if (element instanceof JobHistoryModel) {
return TPromise.as(undefined);
} else {
return TPromise.as(new JobHistoryModel());
}
}
public set data(data: JobHistoryRow[]) {
this._data = data;
}
}
export interface IListTemplate {
statusIcon: HTMLElement;
label: HTMLElement;
}
export class JobHistoryRenderer implements tree.IRenderer {
private _statusIcon: HTMLElement;
public getHeight(tree: tree.ITree, element: JobHistoryRow): number {
return 22;
}
public getTemplateId(tree: tree.ITree, element: JobHistoryRow | JobHistoryModel): string {
if (element instanceof JobHistoryModel) {
return 'jobHistoryModel';
} else {
return 'jobHistoryInfo';
}
}
public renderTemplate(tree: tree.ITree, templateId: string, container: HTMLElement): IListTemplate {
let row = DOM.$('.list-row');
let label = DOM.$('.label');
this._statusIcon = this.createStatusIcon();
row.appendChild(this._statusIcon);
row.appendChild(label);
container.appendChild(row);
let statusIcon = this._statusIcon;
return { statusIcon, label };
}
public renderElement(tree: tree.ITree, element: JobHistoryRow, templateId: string, templateData: IListTemplate): void {
templateData.label.innerText = element.runDate + '\t\t\t' + element.runStatus;
let statusClass: string;
if (element.runStatus === 'Succeeded') {
statusClass = ' passed';
} else if (element.runStatus === 'Failed') {
statusClass = ' failed';
} else {
statusClass = ' unknown';
}
this._statusIcon.className += statusClass;
}
public disposeTemplate(tree: tree.ITree, templateId: string, templateData: IListTemplate): void {
// no op
}
private createStatusIcon(): HTMLElement {
let statusIcon: HTMLElement = DOM.$('div');
statusIcon.className += ' status-icon';
return statusIcon;
}
}
export class JobHistoryFilter implements tree.IFilter {
private _filterString: string;
public isVisible(tree: tree.ITree, element: JobHistoryRow): boolean {
return this._isJobVisible();
}
private _isJobVisible(): boolean {
return true;
}
public set filterString(val: string) {
this._filterString = val;
}
}

View 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.
*--------------------------------------------------------------------------------------------*/
-->
<h1 class="job-heading">Jobs</h1>
<div #jobsgrid class="jobview-grid"></div>

View File

@@ -0,0 +1,255 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!sql/parts/grid/media/slickColorTheme';
import 'vs/css!sql/parts/grid/media/flexbox';
import 'vs/css!sql/parts/grid/media/styles';
import 'vs/css!sql/parts/grid/media/slick.grid';
import 'vs/css!sql/parts/grid/media/slickGrid';
import 'vs/css!../common/media/jobs';
import 'vs/css!../common/media/detailview';
import { OnInit, Component, Inject, forwardRef, ElementRef, ChangeDetectorRef, OnDestroy, ViewChild } from '@angular/core';
import * as Utils from 'sql/parts/connection/common/utils';
import { RefreshWidgetAction, EditDashboardAction } from 'sql/parts/dashboard/common/actions';
import { IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IDisposable } from 'vs/base/common/lifecycle';
import * as themeColors from 'vs/workbench/common/theme';
import { DashboardPage } from 'sql/parts/dashboard/common/dashboardPage.component';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { IBootstrapService, BOOTSTRAP_SERVICE_ID } from 'sql/services/bootstrap/bootstrapService';
import { IJobManagementService } from '../common/interfaces';
import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
import * as sqlops from 'sqlops';
import * as vscode from 'vscode';
import * as nls from 'vs/nls';
import { IGridDataSet } from 'sql/parts/grid/common/interfaces';
import { FieldType, IObservableCollection, CollectionChange, SlickGrid } from 'angular2-slickgrid';
import { Table } from 'sql/base/browser/ui/table/table';
import { attachTableStyler } from 'sql/common/theme/styler';
import { JobHistoryComponent } from './jobHistory.component';
import { AgentViewComponent } from '../agent/agentView.component';
import { RowDetailView } from 'sql/base/browser/ui/table/plugins/rowdetailview';
export const JOBSVIEW_SELECTOR: string = 'jobsview-component';
@Component({
selector: JOBSVIEW_SELECTOR,
templateUrl: decodeURI(require.toUrl('./jobsView.component.html'))
})
export class JobsViewComponent implements OnInit, OnDestroy {
private _jobManagementService: IJobManagementService;
private _disposables = new Array<vscode.Disposable>();
private columns: Array<Slick.Column<any>> = [
{ name: 'Name', field: 'name', formatter: this.renderName, width: 200, },
{ name: 'Last Run', field: 'lastRun' },
{ name: 'Next Run', field: 'nextRun' },
{ name: 'Enabled', field: 'enabled' },
{ name: 'Status', field: 'currentExecutionStatus' },
{ name: 'Category', field: 'category' },
{ name: 'Runnable', field: 'runnable' },
{ name: 'Schedule', field: 'hasSchedule' },
{ name: 'Category ID', field: 'categoryId' },
{ name: 'Last Run Outcome', field: 'lastRunOutcome' },
];
private rowDetail: any;
private dataView: any;
@ViewChild('jobsgrid') _gridEl: ElementRef;
private isVisible: boolean = false;
private isInitialized: boolean = false;
private _table: Table<any>;
public jobs: sqlops.AgentJobInfo[];
public jobHistories: { [jobId: string]: sqlops.AgentJobHistoryInfo[]; } = Object.create(null);
constructor(
@Inject(BOOTSTRAP_SERVICE_ID) private bootstrapService: IBootstrapService,
@Inject(forwardRef(() => DashboardServiceInterface)) private _dashboardService: DashboardServiceInterface,
@Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef,
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef,
@Inject(forwardRef(() => AgentViewComponent)) private _agentViewComponent: AgentViewComponent
) {
this._jobManagementService = bootstrapService.jobManagementService;
}
ngAfterContentChecked() {
if (this.isVisible === false && this._gridEl.nativeElement.offsetParent !== null) {
this.isVisible = true;
if (!this.isInitialized) {
this.onFirstVisible();
this.isInitialized = true;
}
} else if (this.isVisible === true && this._gridEl.nativeElement.offsetParent === null) {
this.isVisible = false;
}
}
loadJobHistories() {
if (this.jobs) {
this.jobs.forEach((job) => {
let ownerUri: string = this._dashboardService.connectionManagementService.connectionInfo.ownerUri;
this._jobManagementService.getJobHistory(ownerUri, job.jobId).then((result) => {
if (result.jobs) {
this.jobHistories[job.jobId] = result.jobs;
this.expandJobsWithFailures();
}
});
});
}
}
private expandJobsWithFailures(): void {
for (let i: number = 0; i < this.jobs.length; ++i) {
let job = this.jobs[i];
let jobHistory = this.jobHistories[job.jobId];
if (jobHistory && jobHistory.length > 0) {
let latestExecution = jobHistory[jobHistory.length - 1];
if (latestExecution.runStatus !== 0) {
this.expandJobRowDetails(i);
}
}
}
}
private expandJobRowDetails(rowIdx: number): void {
}
onFirstVisible() {
let self = this;
let columns = this.columns.map((column) => {
column.rerenderOnResize = true;
return column;
});
let options = <Slick.GridOptions<any>>{
syncColumnCellResize: true,
enableColumnReorder: false,
rowHeight: 45,
enableCellNavigation: true
};
this.dataView = new Slick.Data.DataView({ inlineFilters: false });
let rowDetail = new RowDetailView({
cssClass: 'detailView-toggle',
preTemplate: this.loadingTemplate,
process: (job) => {
(<any>rowDetail).onAsyncResponse.notify({
'itemDetail': job
}, undefined, this);
},
panelRows: 2
});
this.rowDetail = rowDetail;
columns.unshift(this.rowDetail.getColumnDefinition());
this._table = new Table(this._gridEl.nativeElement, undefined, columns, options);
this._table.grid.setData(this.dataView, true);
this._table.grid.onClick.subscribe((e, args) => {
let job = self.getJob(args);
self._agentViewComponent.jobId = job.jobId;
self._agentViewComponent.agentJobInfo = job;
self.getJobHistoryInfo(ownerUri, job).then(result => {
if (result) {
this._agentViewComponent.agentJobHistoryInfo = result;
}
});
self.isVisible = false;
self._agentViewComponent.showHistory = true;
});
this._cd.detectChanges();
let ownerUri: string = this._dashboardService.connectionManagementService.connectionInfo.ownerUri;
this._jobManagementService.getJobs(ownerUri).then((result) => {
if (result && result.jobs) {
this.jobs = result.jobs;
this.onJobsAvailable(result.jobs);
}
});
}
getJobHistoryInfo(ownerUri: string, job: any): Thenable<sqlops.AgentJobHistoryInfo[]> {
return new Promise<sqlops.AgentJobHistoryInfo[]>((resolve, reject) => {
if (this.jobHistories[job.jobId]){
Promise.resolve(this.jobHistories[job.jobId]);
} else {
this._jobManagementService.getJobHistory(ownerUri, job.jobId).then(result => {
if (result && result.jobs) {
Promise.resolve(result.jobs);
} else {
Promise.reject(undefined);
}
});
}
});
}
onJobsAvailable(jobs: sqlops.AgentJobInfo[]) {
let jobViews = jobs.map((job) => {
return {
id: job.jobId,
jobId: job.jobId,
name: job.name,
lastRun: job.lastRun,
nextRun: job.nextRun,
enabled: job.enabled,
currentExecutionStatus: job.currentExecutionStatus,
category: job.category,
runnable: job.runnable,
hasSchedule: job.hasSchedule,
categoryId: job.categoryId,
lastRunOutcome: job.lastRunOutcome
};
});
this._table.registerPlugin(<any>this.rowDetail);
this.rowDetail.onBeforeRowDetailToggle.subscribe(function(e, args) {
});
this.rowDetail.onAfterRowDetailToggle.subscribe(function(e, args) {
});
this.rowDetail.onAsyncEndUpdate.subscribe(function(e, args) {
});
this.dataView.beginUpdate();
this.dataView.setItems(jobViews);
this.dataView.endUpdate();
this._table.resizeCanvas();
this._table.autosizeColumns();
this.loadJobHistories();
}
ngOnInit() {
}
ngOnDestroy() {
}
loadingTemplate() {
return '<div class="preload">Loading...</div>';
}
renderName(row, cell, value, columnDef, dataContext) {
return '<table class="jobview-jobnametable"><tr class="jobview-jobnamerow">' +
'<td nowrap class="jobview-jobnameindicatorsuccess"></td>' +
'<td nowrap class="jobview-jobnametext">' + dataContext.name + '</td>' +
'</tr></table>';
}
private getJob(args: Slick.OnClickEventArgs<any>): sqlops.AgentJobInfo {
let cell = args.cell;
let jobName = args.grid.getCellNode(1, cell).innerText.trim();
let job = this.jobs.filter(job => job.name === jobName)[0];
return job;
}
}

View File

@@ -41,6 +41,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IJobManagementService } from 'sql/parts/jobManagement/common/interfaces';
export const BOOTSTRAP_SERVICE_ID = 'bootstrapService';
export const IBootstrapService = createDecorator<IBootstrapService>(BOOTSTRAP_SERVICE_ID);
@@ -92,6 +93,7 @@ export interface IBootstrapService {
configurationEditorService: ConfigurationEditingService;
commandService: ICommandService;
dashboardWebviewService: IDashboardWebviewService;
jobManagementService: IJobManagementService;
/*
* Bootstraps the Angular module described. Components that need singleton services should inject the

View File

@@ -45,6 +45,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IJobManagementService } from 'sql/parts/jobManagement/common/interfaces';
export class BootstrapService implements IBootstrapService {
@@ -100,7 +101,8 @@ export class BootstrapService implements IBootstrapService {
@IClipboardService public clipboardService: IClipboardService,
@ICapabilitiesService public capabilitiesService: ICapabilitiesService,
@ICommandService public commandService: ICommandService,
@IDashboardWebviewService public dashboardWebviewService: IDashboardWebviewService
@IDashboardWebviewService public dashboardWebviewService: IDashboardWebviewService,
@IJobManagementService public jobManagementService: IJobManagementService
) {
this.configurationEditorService = this.instantiationService.createInstance(ConfigurationEditingService);
this._bootstrapParameterMap = new Map<string, BootstrapParams>();

View File

@@ -53,7 +53,7 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape {
provider.handle = this._nextHandle();
this._adapter.set(provider.handle, provider);
return this._createDisposable(provider.handle);
};
}
$registerConnectionProvider(provider: sqlops.ConnectionProvider): vscode.Disposable {
let rt = this.registerProvider(provider);
@@ -121,6 +121,12 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape {
return rt;
}
$registerAgentServiceProvider(provider: sqlops.AgentServicesProvider): vscode.Disposable {
let rt = this.registerProvider(provider);
this._proxy.$registerAgentServicesProvider(provider.providerId, provider.handle);
return rt;
}
$registerCapabilitiesServiceProvider(provider: sqlops.CapabilitiesProvider): vscode.Disposable {
let rt = this.registerProvider(provider);
this._proxy.$registerCapabilitiesServiceProvider(provider.providerId, provider.handle);
@@ -481,4 +487,30 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape {
public $onSessionEventsAvailable(handle: number, response: sqlops.ProfilerSessionEvents): void {
this._proxy.$onSessionEventsAvailable(handle, response);
}
/**
* Agent Job Provider methods
*/
/**
* Get Agent Job list
*/
public $getJobs(handle: number, ownerUri: string): Thenable<sqlops.AgentJobsResult> {
return this._resolveProvider<sqlops.AgentServicesProvider>(handle).getJobs(ownerUri);
}
/**
* Get a Agent Job's history
*/
public $getJobHistory(handle: number, ownerUri: string, jobID: string): Thenable<sqlops.AgentJobHistoryResult> {
return this._resolveProvider<sqlops.AgentServicesProvider>(handle).getJobHistory(ownerUri, jobID);
}
/**
* Run an action on a job
*/
public $jobAction(handle: number, ownerUri: string, jobName: string, action: string): Thenable<sqlops.AgentJobActionResult> {
return this._resolveProvider<sqlops.AgentServicesProvider>(handle).jobAction(ownerUri, jobName, action);
}
}

View File

@@ -18,6 +18,7 @@ import { IMetadataService } from 'sql/services/metadata/metadataService';
import { IObjectExplorerService } from 'sql/parts/registeredServer/common/objectExplorerService';
import { IScriptingService } from 'sql/services/scripting/scriptingService';
import { IAdminService } from 'sql/parts/admin/common/adminService';
import { IJobManagementService } from 'sql/parts/jobManagement/common/interfaces';
import { IBackupService } from 'sql/parts/disasterRecovery/backup/common/backupService';
import { IRestoreService } from 'sql/parts/disasterRecovery/restore/common/restoreService';
import { ITaskService } from 'sql/parts/taskHistory/common/taskService';
@@ -50,6 +51,7 @@ export class MainThreadDataProtocol implements MainThreadDataProtocolShape {
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
@IScriptingService private _scriptingService: IScriptingService,
@IAdminService private _adminService: IAdminService,
@IJobManagementService private _jobManagementService: IJobManagementService,
@IBackupService private _backupService: IBackupService,
@IRestoreService private _restoreService: IRestoreService,
@ITaskService private _taskService: ITaskService,
@@ -329,6 +331,24 @@ export class MainThreadDataProtocol implements MainThreadDataProtocolShape {
return undefined;
}
public $registerAgentServicesProvider(providerId: string, handle: number): TPromise<any> {
const self = this;
this._jobManagementService.registerProvider(providerId, <sqlops.AgentServicesProvider> {
providerId: providerId,
getJobs(connectionUri: string): Thenable<sqlops.AgentJobsResult> {
return self._proxy.$getJobs(handle, connectionUri);
},
getJobHistory(connectionUri: string, jobID: string): Thenable<sqlops.AgentJobHistoryResult> {
return self._proxy.$getJobHistory(handle, connectionUri, jobID);
},
jobAction(connectionUri: string, jobName: string, action: string): Thenable<sqlops.AgentJobActionResult> {
return self._proxy.$jobAction(handle, connectionUri, jobName, action);
}
});
return undefined;
}
public $registerCapabilitiesServiceProvider(providerId: string, handle: number): TPromise<any> {
const self = this;
this._capabilitiesService.registerProvider(<sqlops.CapabilitiesProvider>{

View File

@@ -28,7 +28,6 @@ import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration
import { ExtHostModalDialogs } from 'sql/workbench/api/node/extHostModalDialog';
import { ExtHostTasks } from 'sql/workbench/api/node/extHostTasks';
import { ILogService } from 'vs/platform/log/common/log';
import { IExtensionApiFactory } from 'vs/workbench/api/node/extHost.api.impl';
import { ExtHostDashboardWebviews } from 'sql/workbench/api/node/extHostDashboardWebview';
import { ExtHostConnectionManagement } from 'sql/workbench/api/node/extHostConnectionManagement';
import { ExtHostDashboard } from 'sql/workbench/api/node/extHostDashboard';
@@ -256,7 +255,7 @@ export function createApiFactory(
};
let registerAgentServicesProvider = (provider: sqlops.AgentServicesProvider): vscode.Disposable => {
return undefined;
return extHostDataProvider.$registerAgentServiceProvider(provider);
};
// namespace: dataprotocol
@@ -272,6 +271,7 @@ export function createApiFactory(
registerTaskServicesProvider,
registerQueryProvider,
registerAdminServicesProvider,
registerAgentServicesProvider,
registerCapabilitiesServiceProvider,
registerAgentServicesProvider,
onDidChangeLanguageFlavor(listener: (e: sqlops.DidChangeLanguageFlavorParams) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) {

View File

@@ -306,6 +306,22 @@ export abstract class ExtHostDataProtocolShape {
* Stop a profiler session
*/
$stopSession(handle: number, sessionId: string): Thenable<boolean> { throw ni(); }
/**
* Get Agent Job list
*/
$getJobs(handle: number, ownerUri: string): Thenable<sqlops.AgentJobsResult>{ throw ni(); }
/**
* Get a Agent Job's history
*/
$getJobHistory(handle: number, ownerUri: string, jobID: string): Thenable<sqlops.AgentJobHistoryResult>{ throw ni(); }
/**
* Run an action on a Job
*/
$jobAction(handle: number, ownerUri: string, jobName: string, action: string): Thenable<sqlops.AgentJobActionResult>{ throw ni(); }
}
/**
@@ -370,6 +386,7 @@ export interface MainThreadDataProtocolShape extends IDisposable {
$registerFileBrowserProvider(providerId: string, handle: number): TPromise<any>;
$registerCapabilitiesServiceProvider(providerId: string, handle: number): TPromise<any>;
$registerAdminServicesProvider(providerId: string, handle: number): TPromise<any>;
$registerAgentServicesProvider(providerId: string, handle: number): TPromise<any>;
$unregisterProvider(handle: number): TPromise<any>;
$onConnectionComplete(handle: number, connectionInfoSummary: sqlops.ConnectionInfoSummary): void;
$onIntelliSenseCacheComplete(handle: number, connectionUri: string): void;

View File

@@ -68,7 +68,7 @@ export class ProductContribution implements IWorkbenchContribution {
text => editorService.openEditor(instantiationService.createInstance(ReleaseNotesInput, pkg.version, text), { pinned: true }),
() => {
messageService.show(Severity.Info, {
message: nls.localize('read the release notes', "Welcome to {0} February Public Preview! Would you like to view the Getting Started Guide?", product.nameLong, pkg.version),
message: nls.localize('read the release notes', "Welcome to {0} March Public Preview! Would you like to view the Getting Started Guide?", product.nameLong, pkg.version),
actions: [
instantiationService.createInstance(OpenGettingStartedInBrowserAction),
CloseAction

View File

@@ -0,0 +1,21 @@
/*---------------------------------------------------------------------------------------------
* 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 assert from 'assert';
import * as TypeMoq from 'typemoq';
import { JobManagementService } from 'sql/parts/jobManagement/common/jobManagementService';
// TESTS ///////////////////////////////////////////////////////////////////
suite('Job Management service tests', () => {
setup(() => {
});
test('Construction - Job Service Initialization', () => {
// ... Create instance of the service and reder account picker
let service = new JobManagementService(undefined, undefined);
});
});

View File

@@ -123,7 +123,8 @@ function registerListeners(enableDeveloperTools) {
require('slickgrid/slick.core');
const Slick = window.Slick;
require('slickgrid/slick.grid');
require('slickgrid/slick.editors');;
require('slickgrid/slick.editors');
require('slickgrid/slick.dataview');
require('reflect-metadata');
require('zone.js');

View File

@@ -123,6 +123,8 @@ import { IQueryManagementService, QueryManagementService } from 'sql/parts/query
import { IEditorDescriptorService, EditorDescriptorService } from 'sql/parts/query/editor/editorDescriptorService';
import { IScriptingService, ScriptingService } from 'sql/services/scripting/scriptingService';
import { IAdminService, AdminService } from 'sql/parts/admin/common/adminService';
import { IJobManagementService } from 'sql/parts/jobManagement/common/interfaces';
import { JobManagementService } from 'sql/parts/jobManagement/common/jobManagementService';
import { IBackupService, IBackupUiService } from 'sql/parts/disasterRecovery/backup/common/backupService';
import { BackupService, BackupUiService } from 'sql/parts/disasterRecovery/backup/common/backupServiceImp';
import { IRestoreDialogController, IRestoreService } from 'sql/parts/disasterRecovery/restore/common/restoreService';
@@ -700,6 +702,7 @@ export class Workbench implements IPartService {
serviceCollection.set(IObjectExplorerService, this.instantiationService.createInstance(ObjectExplorerService));
serviceCollection.set(IScriptingService, this.instantiationService.createInstance(ScriptingService));
serviceCollection.set(IAdminService, this.instantiationService.createInstance(AdminService));
serviceCollection.set(IJobManagementService, this.instantiationService.createInstance(JobManagementService));
serviceCollection.set(IBackupService, this.instantiationService.createInstance(BackupService));
serviceCollection.set(IBackupUiService, this.instantiationService.createInstance(BackupUiService));
serviceCollection.set(IRestoreService, this.instantiationService.createInstance(RestoreService));

View File

@@ -163,6 +163,7 @@ import 'sql/parts/dashboard/widgets/webview/webviewWidget.contribution';
import 'sql/parts/dashboard/dashboardConfig.contribution';
/* Containers */
import 'sql/parts/dashboard/containers/dashboardWebviewContainer.contribution';
import 'sql/parts/dashboard/containers/dashboardControlHostContainer.contribution';
import 'sql/parts/dashboard/containers/dashboardGridContainer.contribution';
import 'sql/parts/dashboard/containers/dashboardWidgetContainer.contribution';
import 'sql/parts/dashboard/containers/dashboardContainer.contribution';