Compare commits

..

15 Commits
1.3.4 ... 1.3.5

Author SHA1 Message Date
Yurong He
0926057bfe Fixed #3294 removed dead code for "attach to" and remove disable to make it respond theme change (#3349)
* Fixed #3294

* Fixed #3294
2018-11-29 19:28:08 -08:00
Karl Burtram
6912e3893e Bump Azure Data Studio to 1.3.5 2018-11-29 17:12:32 -08:00
Karl Burtram
d3052657df Bump SQL Tools to 1.5.0-alpha.60 2018-11-29 17:12:05 -08:00
Karl Burtram
a5ca4d8edf Add ALTER and PROC to the colorization list (#3353) 2018-11-29 17:04:45 -08:00
Anthony Dresser
afb1ebebd5 Result Streaming (#3319)
* handle releasing data when the grid is unrendered

* update sqlops

* add complete to sqlops

* update protocol

* update protocol

* formatting

* update sqlops.d.ts

* stash

* better handling of results streaming

* formatting

* improvments to result streaming

* bump slickgrid and address a performance bottleneck

* remove unnecessary code

* formatting

* update locks

* optimize large values in the grid

* formatting

* formatting

* update yarn

* bump packages

* yarn

* bump

* yarn lock

* locking

* yarn

* fix duplicate result sets

* fix event stream versions

* yarn
2018-11-29 15:16:53 -08:00
Matt Irvine
a04a9eb5ad Hide connection account picker when there are no auth type options (#3350) 2018-11-29 14:54:46 -08:00
Cory Rivera
027badd21f Fix capitalization in dataTierApplicationWizard imports. (#3351) 2018-11-29 14:32:45 -08:00
Raj
1affc760e6 Notebook save functionality through button (#3340)
* 3268: Notebook save using button

* 3268: Misc change

* Handle promise while saving notebook

* Async await functions to run action
2018-11-29 14:10:16 -08:00
Yurong He
3ca72b7398 Fixed Spark UI links within Notebooks are not working notebooks sql2019Preview (#3344)
#3277
2018-11-29 12:52:18 -08:00
Yurong He
702dbddd78 Fixed some issues for Markdown and CSS (#3336)
* Fixed few markdown cell issues
* Change the boolean value from 1 to true
2018-11-29 12:50:53 -08:00
Aditya Bist
8fbecc0227 Fixed agent step update (#3308)
* fixed agent step update

* enabled reordering of steps in edit job
2018-11-29 10:48:12 -08:00
Alan Ren
421271acfa hide the profiler commands meant for internal use (#3339) 2018-11-28 15:03:53 -08:00
Raj
98af76b3ac Build error (#3335) 2018-11-28 10:45:21 -08:00
Raj
3952fdbe2d 3240: Empty cells show thick border (#3242)
* 3240: Empty cells show thick border

* 3240: Refactoring code and markdown css selection +output UI improvement
2018-11-28 09:45:34 -08:00
Yurong He
bc13beaa85 Revert "Hide run button in markdown editor and pull toggleMoreAction to a seperate class (#3321)" (#3328)
This reverts commit 9ea8baca05.
2018-11-27 23:43:16 -08:00
47 changed files with 722 additions and 356 deletions

View File

@@ -9,20 +9,21 @@
"@types/mime": "0.0.29",
"@types/minimatch": "^3.0.3",
"@types/node": "8.0.33",
"@types/xml2js": "0.0.33",
"@types/request": "^2.47.0",
"@types/xml2js": "0.0.33",
"azure-storage": "^2.1.0",
"decompress": "^4.2.0",
"del": "^3.0.0",
"documentdb": "1.13.0",
"service-downloader": "github:anthonydresser/service-downloader#0.1.5",
"fs-extra-promise": "^1.0.1",
"github-releases": "^0.4.1",
"mime": "^1.3.4",
"minimist": "^1.2.0",
"request": "^2.85.0",
"service-downloader": "github:anthonydresser/service-downloader#0.1.5",
"typescript": "2.9.2",
"vscode": "^1.0.1",
"xml2js": "^0.4.17",
"github-releases": "^0.4.1",
"request": "^2.85.0"
"xml2js": "^0.4.17"
},
"scripts": {
"compile": "tsc -p tsconfig.build.json",
@@ -30,4 +31,4 @@
"postinstall": "npm run compile",
"npmCheckJs": "tsc --noEmit"
}
}
}

View File

@@ -571,6 +571,18 @@ deep-assign@^1.0.0:
dependencies:
is-obj "^1.0.0"
del@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/del/-/del-3.0.0.tgz#53ecf699ffcbcb39637691ab13baf160819766e5"
integrity sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=
dependencies:
globby "^6.1.0"
is-path-cwd "^1.0.0"
is-path-in-cwd "^1.0.0"
p-map "^1.1.1"
pify "^3.0.0"
rimraf "^2.2.8"
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
@@ -942,6 +954,29 @@ glob@^5.0.3:
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@^7.0.3:
version "7.1.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^3.0.4"
once "^1.3.0"
path-is-absolute "^1.0.0"
globby@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c"
integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=
dependencies:
array-union "^1.0.1"
glob "^7.0.3"
object-assign "^4.0.1"
pify "^2.0.0"
pinkie-promise "^2.0.0"
glogg@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.1.tgz#dcf758e44789cc3f3d32c1f3562a3676e6a34810"
@@ -1313,6 +1348,25 @@ is-obj@^1.0.0:
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
is-path-cwd@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=
is-path-in-cwd@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52"
integrity sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==
dependencies:
is-path-inside "^1.0.0"
is-path-inside@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036"
integrity sha1-jvW33lBDej/cprToZe96pVy0gDY=
dependencies:
path-is-inside "^1.0.1"
is-posix-bracket@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
@@ -1778,6 +1832,11 @@ os-tmpdir@~1.0.2:
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
p-map@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b"
integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==
parse-glob@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
@@ -1798,6 +1857,11 @@ path-is-absolute@^1.0.0:
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
path-is-inside@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=
pause-stream@0.0.11:
version "0.0.11"
resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
@@ -1820,7 +1884,7 @@ performance-now@^2.1.0:
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
pify@^2.3.0:
pify@^2.0.0, pify@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
@@ -2118,7 +2182,7 @@ requires-port@~1.0.0:
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
rimraf@2:
rimraf@2, rimraf@^2.2.8:
version "2.6.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==

View File

@@ -123,6 +123,7 @@ export class JobStepData implements IAgentDialogData {
stepData.retryInterval = jobStepInfo.retryInterval,
stepData.proxyName = jobStepInfo.proxyName;
stepData.dialogMode = AgentDialogMode.EDIT;
stepData.viaJobDialog = true;
return stepData;
}

View File

@@ -46,7 +46,7 @@ export class JobDialog extends AgentDialog<JobData> {
private readonly EditStepButtonString: string = localize('jobDialog.edit', 'Edit');
private readonly DeleteStepButtonString: string = localize('jobDialog.delete', 'Delete');
private readonly MoveStepUpButtonString: string = localize('jobDialog.moveUp', 'Move Step Up');
private readonly MoveStepDownButtonString: string = localize('jobDialog.moveDown', 'Move Step Up');
private readonly MoveStepDownButtonString: string = localize('jobDialog.moveDown', 'Move Step Down');
// Notifications tab strings
private readonly NotificationsTabTopLabelString: string = localize('jobDialog.notificationsTabTop', 'Actions to perform when the job completes');
@@ -230,7 +230,7 @@ export class JobDialog extends AgentDialog<JobData> {
this.moveStepDownButton = view.modelBuilder.button()
.withProperties({
label: this.MoveStepDownButtonString,
width: 80
width: 120
}).component();
this.moveStepUpButton.enabled = false;
@@ -270,31 +270,87 @@ export class JobDialog extends AgentDialog<JobData> {
this.editStepButton.enabled = false;
this.deleteStepButton.enabled = false;
this.moveStepUpButton.onDidClick(() => {
if (this.stepsTable.selectedRows.length === 1) {
let rowNumber = this.stepsTable.selectedRows[0];
// if it's not the first step
if (rowNumber !== 0) {
let previousRow = rowNumber - 1;
let previousStep = this.steps[previousRow];
let previousStepId = this.steps[previousRow].id;
let currentStep = this.steps[rowNumber];
let currentStepId = this.steps[rowNumber].id;
this.steps[previousRow] = currentStep;
this.steps[rowNumber] = previousStep;
this.stepsTable.data = this.convertStepsToData(this.steps);
this.steps[previousRow].id = previousStepId;
this.steps[rowNumber].id = currentStepId;
}
}
});
this.moveStepDownButton.onDidClick(() => {
if (this.stepsTable.selectedRows.length === 1) {
let rowNumber = this.stepsTable.selectedRows[0];
// if it's not the last step
if (this.steps.length !== rowNumber + 1) {
let nextRow = rowNumber + 1;
let nextStep = this.steps[nextRow];
let nextStepId = this.steps[nextRow].id;
let currentStep = this.steps[rowNumber];
let currentStepId = this.steps[rowNumber].id;
this.steps[nextRow] = currentStep;
this.steps[rowNumber] = nextStep;
this.stepsTable.data = this.convertStepsToData(this.steps);
this.steps[nextRow].id = nextStepId;
this.steps[rowNumber].id = currentStepId;
}
}
});
this.editStepButton.onDidClick(() => {
if (this.stepsTable.selectedRows.length === 1) {
let rowNumber = this.stepsTable.selectedRows[0];
let stepData = this.model.jobSteps[rowNumber];
let editStepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, stepData, true);
editStepDialog.onSuccess((step) => {
let stepInfo = JobStepData.convertToAgentJobStepInfo(step);
for (let i = 0; i < this.steps.length; i++) {
if (this.steps[i].id === stepInfo.id) {
this.steps[i] = stepInfo;
}
}
this.stepsTable.data = this.convertStepsToData(this.steps);
});
editStepDialog.openDialog();
}
});
this.deleteStepButton.onDidClick(() => {
if (this.stepsTable.selectedRows.length === 1) {
let rowNumber = this.stepsTable.selectedRows[0];
AgentUtils.getAgentService().then((agentService) => {
let steps = this.model.jobSteps ? this.model.jobSteps : [];
let stepData = this.model.jobSteps[rowNumber];
agentService.deleteJobStep(this.ownerUri, stepData).then((result) => {
if (result && result.success) {
delete steps[rowNumber];
let data = this.convertStepsToData(steps);
this.stepsTable.data = data;
}
});
});
}
});
this.stepsTable.onRowSelected(() => {
// only let edit or delete steps if there's
// one step selection
if (this.stepsTable.selectedRows.length === 1) {
let rowNumber = this.stepsTable.selectedRows[0];
let stepData = this.model.jobSteps[rowNumber];
this.moveStepUpButton.enabled = true;
this.moveStepDownButton.enabled = true;
this.deleteStepButton.enabled = true;
this.editStepButton.enabled = true;
this.editStepButton.onDidClick(() => {
let stepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, stepData, true);
stepDialog.openDialog();
});
this.deleteStepButton.onDidClick(() => {
AgentUtils.getAgentService().then((agentService) => {
let steps = this.model.jobSteps ? this.model.jobSteps : [];
agentService.deleteJobStep(this.ownerUri, stepData).then((result) => {
if (result && result.success) {
delete steps[rowNumber];
let data = this.convertStepsToData(steps);
this.stepsTable.data = data;
}
});
});
});
}
});

View File

@@ -519,6 +519,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
this.model.failureAction = this.failureActionDropdown.value as string;
this.model.outputFileName = this.outputFileNameBox.value;
this.model.appendToLogFile = this.appendToExistingFileCheckbox.checked;
this.model.command = this.commandTextBox.value ? this.commandTextBox.value : '';
}
public async initializeDialog() {

View File

@@ -67,7 +67,7 @@
}
},
"dependencies": {
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.2.7",
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.2.10",
"opener": "^1.4.3",
"service-downloader": "github:anthonydresser/service-downloader#0.1.5",
"vscode-extension-telemetry": "0.0.18",

View File

@@ -7,7 +7,7 @@
import * as sqlops from 'sqlops';
import * as nls from 'vscode-nls';
import { DacFxDataModel } from '../api/models';
import { DataTierApplicationWizard, Operation } from '../DataTierApplicationWizard';
import { DataTierApplicationWizard, Operation } from '../dataTierApplicationWizard';
import { BasePage } from '../api/basePage';
const localize = nls.loadMessageBundle();

View File

@@ -11,7 +11,7 @@ agent-base@4, agent-base@^4.1.0:
applicationinsights@1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/applicationinsights/-/applicationinsights-1.0.1.tgz#53446b830fe8d5d619eee2a278b31d3d25030927"
resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.1.tgz#53446b830fe8d5d619eee2a278b31d3d25030927"
integrity sha1-U0Rrgw/o1dYZ7uKieLMdPSUDCSc=
dependencies:
diagnostic-channel "0.2.0"
@@ -36,7 +36,7 @@ buffer-alloc-unsafe@^1.1.0:
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
buffer-alloc@^1.1.0:
buffer-alloc@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
@@ -75,19 +75,26 @@ core-util-is@~1.0.0:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.2.7":
version "0.2.6"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/85653d8b305af8aef334728d71f07bdc240dfcb7"
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.2.10":
version "0.2.10"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/4de3f7caf0eba54159911b977ddb4f5d7c0a9ca8"
dependencies:
vscode-languageclient "3.5.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"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"
debug@^3.1.0:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
dependencies:
ms "^2.1.1"
decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1"
@@ -143,12 +150,12 @@ decompress@^4.2.0:
diagnostic-channel-publishers@0.2.1:
version "0.2.1"
resolved "https://registry.npmjs.org/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3"
resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3"
integrity sha1-ji1geottef6IC1SLxYzGvrKIxPM=
diagnostic-channel@0.2.0:
version "0.2.0"
resolved "https://registry.npmjs.org/diagnostic-channel/-/diagnostic-channel-0.2.0.tgz#cc99af9612c23fb1fff13612c72f2cbfaa8d5a17"
resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-0.2.0.tgz#cc99af9612c23fb1fff13612c72f2cbfaa8d5a17"
integrity sha1-zJmvlhLCP7H/8TYSxy8sv6qNWhc=
dependencies:
semver "^5.3.0"
@@ -161,9 +168,9 @@ end-of-stream@^1.0.0:
once "^1.4.0"
es6-promise@^4.0.3:
version "4.2.4"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29"
integrity sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==
version "4.2.5"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.5.tgz#da6d0d5692efb461e082c14817fe2427d8f5d054"
integrity sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==
es6-promisify@^5.0.0:
version "5.0.0"
@@ -213,9 +220,9 @@ get-stream@^2.2.0:
pinkie-promise "^2.0.0"
graceful-fs@^4.1.10:
version "4.1.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=
version "4.1.15"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
"graceful-readlink@>= 1.0.0":
version "1.0.1"
@@ -287,6 +294,11 @@ ms@2.0.0:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
ms@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
object-assign@^4.0.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
@@ -300,9 +312,9 @@ once@^1.4.0:
wrappy "1"
opener@^1.4.3:
version "1.4.3"
resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8"
integrity sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=
version "1.5.1"
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed"
integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==
os-tmpdir@~1.0.2:
version "1.0.2"
@@ -368,7 +380,7 @@ seek-bzip@^1.0.5:
semver@^5.3.0:
version "5.6.0"
resolved "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
"service-downloader@github:anthonydresser/service-downloader#0.1.5":
@@ -397,16 +409,16 @@ strip-dirs@^2.0.0:
is-natural-number "^4.0.1"
tar-stream@^1.5.2:
version "1.6.1"
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.1.tgz#f84ef1696269d6223ca48f6e1eeede3f7e81f395"
integrity sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==
version "1.6.2"
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555"
integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==
dependencies:
bl "^1.0.0"
buffer-alloc "^1.1.0"
buffer-alloc "^1.2.0"
end-of-stream "^1.0.0"
fs-constants "^1.0.0"
readable-stream "^2.3.0"
to-buffer "^1.1.0"
to-buffer "^1.1.1"
xtend "^4.0.0"
through@^2.3.6:
@@ -421,15 +433,15 @@ tmp@^0.0.33:
dependencies:
os-tmpdir "~1.0.2"
to-buffer@^1.1.0:
to-buffer@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==
unbzip2-stream@^1.0.9:
version "1.2.5"
resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz#73a033a567bbbde59654b193c44d48a7e4f43c47"
integrity sha512-izD3jxT8xkzwtXRUZjtmRwKnZoeECrfZ8ra/ketwOcusbZEp4mjULMnJOCfTDZBgGQAAY1AJ/IgxcwkavcX9Og==
version "1.3.1"
resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz#7854da51622a7e63624221196357803b552966a1"
integrity sha512-fIZnvdjblYs7Cru/xC6tCPVhz7JkYcVQQkePwMLyQELzYTds2Xn8QefPVnvdVhhZqubxNA1cASXEH5wcK0Bucw==
dependencies:
buffer "^3.0.1"
through "^2.3.6"
@@ -441,7 +453,7 @@ util-deprecate@~1.0.1:
vscode-extension-telemetry@0.0.18:
version "0.0.18"
resolved "https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.18.tgz#602ba20d8c71453aa34533a291e7638f6e5c0327"
resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.18.tgz#602ba20d8c71453aa34533a291e7638f6e5c0327"
integrity sha512-Vw3Sr+dZwl+c6PlsUwrTtCOJkgrmvS3OUVDQGcmpXWAgq9xGq6as0K4pUx+aGqTjzLAESmWSrs6HlJm6J6Khcg==
dependencies:
applicationinsights "1.0.1"
@@ -472,9 +484,9 @@ vscode-languageserver-types@3.5.0:
integrity sha1-5I15li8LjgLelV4/UkkI4rGcA3Q=
vscode-nls@^3.2.1:
version "3.2.4"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"
integrity sha512-FTjdqa4jDDoBjJqr36O8lmmZf/55kQ2w4ZY/+GL6K92fq765BqO3aYw21atnXUno/P04V5DWagNl4ybDIndJsw==
version "3.2.5"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.5.tgz#25520c1955108036dec607c85e00a522f247f1a4"
integrity sha512-ITtoh3V4AkWXMmp3TB97vsMaHRgHhsSFPsUdzlueSL+dRZbSNTZeOmdQv60kjCV306ghPxhDeoNUEm3+EZMuyw==
wrappy@1:
version "1.0.2"
@@ -496,5 +508,5 @@ yauzl@^2.4.2:
zone.js@0.7.6:
version "0.7.6"
resolved "https://registry.npmjs.org/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009"
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009"
integrity sha1-+7w50+AmHQmG8boGMG6zrrDSIAk=

View File

@@ -18,7 +18,7 @@
"update-grammar": "node ../../build/npm/update-grammar.js Microsoft/vscode-mssql syntaxes/SQL.plist ./syntaxes/sql.tmLanguage.json"
},
"dependencies": {
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.2.9",
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.2.10",
"opener": "^1.4.3",
"service-downloader": "github:anthonydresser/service-downloader#0.1.5",
"vscode-extension-telemetry": "^0.0.15"

View File

@@ -1,6 +1,6 @@
{
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
"version": "1.5.0-alpha.59",
"version": "1.5.0-alpha.60",
"downloadFileNames": {
"Windows_86": "win-x86-netcoreapp2.2.zip",
"Windows_64": "win-x64-netcoreapp2.2.zip",

View File

@@ -36,7 +36,7 @@ buffer-alloc-unsafe@^1.1.0:
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
buffer-alloc@^1.1.0:
buffer-alloc@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
@@ -75,19 +75,26 @@ core-util-is@~1.0.0:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.2.9":
version "0.2.9"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/0a3c0f22940d1c67bb567171508ccb1169c6313a"
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.2.10":
version "0.2.10"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/4de3f7caf0eba54159911b977ddb4f5d7c0a9ca8"
dependencies:
vscode-languageclient "3.5.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"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"
debug@^3.1.0:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
dependencies:
ms "^2.1.1"
decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1"
@@ -161,9 +168,9 @@ end-of-stream@^1.0.0:
once "^1.4.0"
es6-promise@^4.0.3:
version "4.2.4"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29"
integrity sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==
version "4.2.5"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.5.tgz#da6d0d5692efb461e082c14817fe2427d8f5d054"
integrity sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==
es6-promisify@^5.0.0:
version "5.0.0"
@@ -213,9 +220,9 @@ get-stream@^2.2.0:
pinkie-promise "^2.0.0"
graceful-fs@^4.1.10:
version "4.1.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=
version "4.1.15"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
"graceful-readlink@>= 1.0.0":
version "1.0.1"
@@ -287,6 +294,11 @@ ms@2.0.0:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
ms@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
object-assign@^4.0.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
@@ -300,9 +312,9 @@ once@^1.4.0:
wrappy "1"
opener@^1.4.3:
version "1.4.3"
resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8"
integrity sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=
version "1.5.1"
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed"
integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==
os-tmpdir@~1.0.2:
version "1.0.2"
@@ -367,9 +379,9 @@ seek-bzip@^1.0.5:
commander "~2.8.1"
semver@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==
version "5.6.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
"service-downloader@github:anthonydresser/service-downloader#0.1.5":
version "0.1.5"
@@ -397,16 +409,16 @@ strip-dirs@^2.0.0:
is-natural-number "^4.0.1"
tar-stream@^1.5.2:
version "1.6.1"
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.1.tgz#f84ef1696269d6223ca48f6e1eeede3f7e81f395"
integrity sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==
version "1.6.2"
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555"
integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==
dependencies:
bl "^1.0.0"
buffer-alloc "^1.1.0"
buffer-alloc "^1.2.0"
end-of-stream "^1.0.0"
fs-constants "^1.0.0"
readable-stream "^2.3.0"
to-buffer "^1.1.0"
to-buffer "^1.1.1"
xtend "^4.0.0"
through@^2.3.6:
@@ -421,15 +433,15 @@ tmp@^0.0.33:
dependencies:
os-tmpdir "~1.0.2"
to-buffer@^1.1.0:
to-buffer@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==
unbzip2-stream@^1.0.9:
version "1.2.5"
resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz#73a033a567bbbde59654b193c44d48a7e4f43c47"
integrity sha512-izD3jxT8xkzwtXRUZjtmRwKnZoeECrfZ8ra/ketwOcusbZEp4mjULMnJOCfTDZBgGQAAY1AJ/IgxcwkavcX9Og==
version "1.3.1"
resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz#7854da51622a7e63624221196357803b552966a1"
integrity sha512-fIZnvdjblYs7Cru/xC6tCPVhz7JkYcVQQkePwMLyQELzYTds2Xn8QefPVnvdVhhZqubxNA1cASXEH5wcK0Bucw==
dependencies:
buffer "^3.0.1"
through "^2.3.6"

View File

@@ -26,8 +26,7 @@
"Microsoft.mssql"
],
"contributes": {
"commands": [
{
"commands": [{
"command": "profiler.newProfiler",
"title": "Launch Profiler",
"category": "Profiler"
@@ -49,13 +48,23 @@
}
],
"menus": {
"objectExplorer/item/context": [
"commandPalette": [{
"command": "profiler.start",
"when": "False"
},
{
"command": "profiler.newProfiler",
"when": "connectionProvider == MSSQL && nodeType && nodeType == Server",
"group": "profiler"
"command": "profiler.stop",
"when": "False"
}, {
"command": "profiler.openCreateSessionDialog",
"when": "False"
}
]
],
"objectExplorer/item/context": [{
"command": "profiler.newProfiler",
"when": "connectionProvider == MSSQL && nodeType && nodeType == Server",
"group": "profiler"
}]
},
"outputChannels": [
"sqlprofiler"

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
{
"name": "azuredatastudio",
"version": "1.3.4",
"version": "1.3.5",
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
"author": {
"name": "Microsoft Corporation"
@@ -68,7 +68,7 @@
"rxjs": "5.4.0",
"sanitize-html": "^1.19.1",
"semver": "^5.5.0",
"slickgrid": "github:anthonydresser/SlickGrid#2.3.28",
"slickgrid": "github:anthonydresser/SlickGrid#2.3.29",
"spdlog": "0.7.1",
"sudo-prompt": "8.2.0",
"svg.js": "^2.2.5",
@@ -174,6 +174,7 @@
"windows-process-tree": "0.2.2"
},
"resolutions": {
"rc": "1.2.8"
"rc": "1.2.8",
"event-stream": "3.3.4"
}
}

View File

@@ -9,36 +9,27 @@ export interface IObservableCollection<T> {
getLength(): number;
at(index: number): T;
getRange(start: number, end: number): T[];
setCollectionChangedCallback(callback: (change: CollectionChange, startIndex: number, count: number) => void): void;
setCollectionChangedCallback(callback: (startIndex: number, count: number) => void): void;
setLength(number): void;
dispose(): void;
}
export interface IGridDataRow {
row?: number;
values: any[];
}
export enum CollectionChange {
ItemsReplaced
}
class LoadCancellationToken {
isCancelled: boolean;
}
class DataWindow<TData> {
private _data: TData[];
class DataWindow<T> {
private _data: T[];
private _length: number = 0;
private _offsetFromDataSource: number = -1;
private lastLoadCancellationToken: LoadCancellationToken;
constructor(
private loadFunction: (offset: number, count: number) => Thenable<TData[]>,
private placeholderItemGenerator: (index: number) => TData,
private loadFunction: (offset: number, count: number) => Thenable<T[]>,
private placeholderItemGenerator: (index: number) => T,
private loadCompleteCallback: (start: number, end: number) => void
) {
}
) { }
dispose() {
this._data = undefined;
@@ -50,26 +41,26 @@ class DataWindow<TData> {
}
}
getStartIndex(): number {
public getStartIndex(): number {
return this._offsetFromDataSource;
}
getEndIndex(): number {
public getEndIndex(): number {
return this._offsetFromDataSource + this._length;
}
contains(dataSourceIndex: number): boolean {
public contains(dataSourceIndex: number): boolean {
return dataSourceIndex >= this.getStartIndex() && dataSourceIndex < this.getEndIndex();
}
getItem(index: number): TData {
public getItem(index: number): T {
if (!this._data) {
return this.placeholderItemGenerator(index);
}
return this._data[index - this._offsetFromDataSource];
}
positionWindow(offset: number, length: number): void {
public positionWindow(offset: number, length: number): void {
this._offsetFromDataSource = offset;
this._length = length;
this._data = undefined;
@@ -92,34 +83,28 @@ class DataWindow<TData> {
}
}
export class VirtualizedCollection<TData> implements IObservableCollection<TData> {
export class VirtualizedCollection<T extends Slick.SlickData> implements IObservableCollection<T> {
private _bufferWindowBefore: DataWindow<T>;
private _window: DataWindow<T>;
private _bufferWindowAfter: DataWindow<T>;
private _length: number;
private _windowSize: number;
private _bufferWindowBefore: DataWindow<TData>;
private _window: DataWindow<TData>;
private _bufferWindowAfter: DataWindow<TData>;
private collectionChangedCallback: (change: CollectionChange, startIndex: number, count: number) => void;
private collectionChangedCallback: (startIndex: number, count: number) => void;
constructor(
windowSize: number,
length: number,
loadFn: (offset: number, count: number) => Thenable<TData[]>,
private _placeHolderGenerator: (index: number) => TData
private readonly windowSize: number,
private placeHolderGenerator: (index: number) => T,
private length: number,
loadFn: (offset: number, count: number) => Thenable<T[]>
) {
this._windowSize = windowSize;
this._length = length;
let loadCompleteCallback = (start: number, end: number) => {
if (this.collectionChangedCallback) {
this.collectionChangedCallback(CollectionChange.ItemsReplaced, start, end - start);
this.collectionChangedCallback(start, end - start);
}
};
this._bufferWindowBefore = new DataWindow(loadFn, _placeHolderGenerator, loadCompleteCallback);
this._window = new DataWindow(loadFn, _placeHolderGenerator, loadCompleteCallback);
this._bufferWindowAfter = new DataWindow(loadFn, _placeHolderGenerator, loadCompleteCallback);
this._bufferWindowBefore = new DataWindow(loadFn, placeHolderGenerator, loadCompleteCallback);
this._window = new DataWindow(loadFn, placeHolderGenerator, loadCompleteCallback);
this._bufferWindowAfter = new DataWindow(loadFn, placeHolderGenerator, loadCompleteCallback);
}
dispose() {
@@ -128,19 +113,23 @@ export class VirtualizedCollection<TData> implements IObservableCollection<TData
this._window.dispose();
}
setCollectionChangedCallback(callback: (change: CollectionChange, startIndex: number, count: number) => void): void {
public setCollectionChangedCallback(callback: (startIndex: number, count: number) => void): void {
this.collectionChangedCallback = callback;
}
getLength(): number {
return this._length;
public getLength(): number {
return this.length;
}
at(index: number): TData {
setLength(number: any): void {
this.length = number;
}
public at(index: number): T {
return this.getRange(index, index + 1)[0];
}
getRange(start: number, end: number): TData[] {
public getRange(start: number, end: number): T[] {
// current data may contain placeholders
let currentData = this.getRangeFromCurrent(start, end);
@@ -155,7 +144,7 @@ export class VirtualizedCollection<TData> implements IObservableCollection<TData
this._bufferWindowAfter = this._window;
this._window = this._bufferWindowBefore;
this._bufferWindowBefore = windowToRecycle;
let newWindowOffset = Math.max(0, this._window.getStartIndex() - this._windowSize);
let newWindowOffset = Math.max(0, this._window.getStartIndex() - this.windowSize);
this._bufferWindowBefore.positionWindow(newWindowOffset, this._window.getStartIndex() - newWindowOffset);
} else if (start >= this._bufferWindowAfter.getStartIndex()) {
@@ -164,8 +153,8 @@ export class VirtualizedCollection<TData> implements IObservableCollection<TData
this._bufferWindowBefore = this._window;
this._window = this._bufferWindowAfter;
this._bufferWindowAfter = windowToRecycle;
let newWindowOffset = Math.min(this._window.getStartIndex() + this._windowSize, this._length);
let newWindowLength = Math.min(this._length - newWindowOffset, this._windowSize);
let newWindowOffset = Math.min(this._window.getStartIndex() + this.windowSize, this.length);
let newWindowLength = Math.min(this.length - newWindowOffset, this.windowSize);
this._bufferWindowAfter.positionWindow(newWindowOffset, newWindowLength);
}
@@ -173,7 +162,7 @@ export class VirtualizedCollection<TData> implements IObservableCollection<TData
return currentData;
}
private getRangeFromCurrent(start: number, end: number): TData[] {
private getRangeFromCurrent(start: number, end: number): T[] {
let currentData = [];
for (let i = 0; i < end - start; i++) {
currentData.push(this.getDataFromCurrent(start + i));
@@ -182,7 +171,7 @@ export class VirtualizedCollection<TData> implements IObservableCollection<TData
return currentData;
}
private getDataFromCurrent(index: number): TData {
private getDataFromCurrent(index: number): T {
if (this._bufferWindowBefore.contains(index)) {
return this._bufferWindowBefore.getItem(index);
} else if (this._bufferWindowAfter.contains(index)) {
@@ -191,39 +180,47 @@ export class VirtualizedCollection<TData> implements IObservableCollection<TData
return this._window.getItem(index);
}
return this._placeHolderGenerator(index);
return this.placeHolderGenerator(index);
}
private resetWindowsAroundIndex(index: number): void {
let bufferWindowBeforeStart = Math.max(0, index - this._windowSize * 1.5);
let bufferWindowBeforeEnd = Math.max(0, index - this._windowSize / 2);
let bufferWindowBeforeStart = Math.max(0, index - this.windowSize * 1.5);
let bufferWindowBeforeEnd = Math.max(0, index - this.windowSize / 2);
this._bufferWindowBefore.positionWindow(bufferWindowBeforeStart, bufferWindowBeforeEnd - bufferWindowBeforeStart);
let mainWindowStart = bufferWindowBeforeEnd;
let mainWindowEnd = Math.min(mainWindowStart + this._windowSize, this._length);
let mainWindowEnd = Math.min(mainWindowStart + this.windowSize, this.length);
this._window.positionWindow(mainWindowStart, mainWindowEnd - mainWindowStart);
let bufferWindowAfterStart = mainWindowEnd;
let bufferWindowAfterEnd = Math.min(bufferWindowAfterStart + this._windowSize, this._length);
let bufferWindowAfterEnd = Math.min(bufferWindowAfterStart + this.windowSize, this.length);
this._bufferWindowAfter.positionWindow(bufferWindowAfterStart, bufferWindowAfterEnd - bufferWindowAfterStart);
}
}
export class AsyncDataProvider<TData extends IGridDataRow> implements IDisposableDataProvider<TData> {
export class AsyncDataProvider<T extends Slick.SlickData> implements IDisposableDataProvider<T> {
constructor(private dataRows: IObservableCollection<TData>) { }
constructor(public dataRows: IObservableCollection<T>) { }
public getLength(): number {
return this.dataRows ? this.dataRows.getLength() : 0;
return this.dataRows.getLength();
}
public getItem(index: number): TData {
return !this.dataRows ? undefined : this.dataRows.at(index);
public getItem(index: number): T {
return this.dataRows.at(index);
}
public getRange(start: number, end: number): TData[] {
return !this.dataRows ? undefined : this.dataRows.getRange(start, end);
public getRange(start: number, end: number): T[] {
return this.dataRows.getRange(start, end);
}
public set length(length: number) {
this.dataRows.setLength(length);
}
public get length(): number {
return this.dataRows.getLength();
}
dispose() {

View File

@@ -5,8 +5,6 @@
'use strict';
import { range } from 'vs/base/common/arrays';
export interface IRowNumberColumnOptions {
numberOfRows: number;
cssClass?: string;
@@ -17,7 +15,7 @@ const sizePerDigit = 15;
export class RowNumberColumn<T> implements Slick.Plugin<T> {
private handler = new Slick.EventHandler();
private grid: Slick.Grid<T>;
private currentColumnWidth: number;
constructor(private options: IRowNumberColumnOptions) {
}
@@ -52,19 +50,25 @@ export class RowNumberColumn<T> implements Slick.Plugin<T> {
}
}
public updateRowCount(rowNum: number) {
this.options.numberOfRows = rowNum;
let columnWidth = Math.max(this.options.numberOfRows.toString().length * sizePerDigit, 22);
if (columnWidth !== this.currentColumnWidth) {
this.grid.setColumnWidths([this.getColumnDefinition()]);
}
}
public getColumnDefinition(): Slick.Column<T> {
// that smallest we can make it is 22 due to padding and margins in the cells
let columnWidth = Math.max(this.options.numberOfRows.toString().length * sizePerDigit, 22);
this.currentColumnWidth = Math.max(this.options.numberOfRows.toString().length * sizePerDigit, 22);
return {
id: 'rowNumber',
name: '',
field: 'rowNumber',
width: columnWidth,
minWidth: columnWidth,
maxWidth: columnWidth,
width: this.currentColumnWidth,
resizable: false,
cssClass: this.options.cssClass,
focusable: false,
focusable: true,
selectable: false,
formatter: (r, c, v, cd, dc) => this.formatter(r, c, v, cd, dc)
};

View File

@@ -545,6 +545,10 @@ export class ConnectionWidget {
if (this._authTypeSelectBox) {
this.onAuthTypeSelected(this._authTypeSelectBox.value);
} else {
let tableContainerElement = this._tableContainer.getContainer();
tableContainerElement.classList.remove('hide-username-password');
tableContainerElement.classList.add('hide-azure-accounts');
}
// Disable connect button if -

View File

@@ -3,7 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { $ } from 'vs/base/browser/dom';
import { escape } from 'sql/base/common/strings';
export class DBCellValue {
@@ -41,20 +40,24 @@ export function hyperLinkFormatter(row: number, cell: any, value: any, columnDef
*/
export function textFormatter(row: number, cell: any, value: any, columnDef: any, dataContext: any): string {
let cellClasses = 'grid-cell-value-container';
let valueToDisplay: string = '';
let valueToDisplay = '';
let titleValue = '';
if (DBCellValue.isDBCellValue(value)) {
valueToDisplay = 'NULL';
if (!value.isNull) {
valueToDisplay = escape(value.displayValue.replace(/(\r\n|\n|\r)/g, ' '));
valueToDisplay = value.displayValue.replace(/(\r\n|\n|\r)/g, ' ');
valueToDisplay = escape(valueToDisplay.length > 250 ? valueToDisplay.slice(0, 250) + '...' : valueToDisplay);
titleValue = value.displayValue;
} else {
cellClasses += ' missing-value';
}
} else if (typeof value === 'string') {
valueToDisplay = escape(value);
valueToDisplay = escape(value.length > 250 ? value.slice(0, 250) + '...' : value);
titleValue = value;
}
return `<span title="${valueToDisplay}" class="${cellClasses}">${valueToDisplay}</span>`;
return `<span title="${titleValue}" class="${cellClasses}">${valueToDisplay}</span>`;
}
/** The following code is a rewrite over the both formatter function using dom builder

View File

@@ -9,6 +9,6 @@
</div>
<div #editor class="editor" style="flex: 1 1 auto; overflow: hidden;">
</div>
<div #moreactions class="toolbar" style="flex: 0 0 auto; display: flex; flex-flow:column; width: 20px; min-height: 20px; max-height: 20px; padding-top: 10px; orientation: portrait">
<div #moreactions class="toolbar" style="flex: 0 0 auto; display: flex; flex-flow:column; width: 20px; min-height: 20px; max-height: 20px; padding-top: 0px; orientation: portrait">
</div>
</div>

View File

@@ -29,7 +29,7 @@ import { IModelService } from 'vs/editor/common/services/modelService';
import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { ICellModel } from 'sql/parts/notebook/models/modelInterfaces';
import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
import { RunCellAction, CellContext, NotebookCellToggleMoreActon } from 'sql/parts/notebook/cellViews/codeActions';
import { RunCellAction, DeleteCellAction, AddCellAction, CellContext } from 'sql/parts/notebook/cellViews/codeActions';
import { NotebookModel } from 'sql/parts/notebook/models/notebookModel';
import { ToggleMoreWidgetAction } from 'sql/parts/dashboard/common/actions';
import { CellTypes } from 'sql/parts/notebook/models/contracts';
@@ -59,14 +59,15 @@ export class CodeComponent extends AngularDisposable implements OnInit, OnChange
}
protected _actionBar: Taskbar;
protected _moreActions: ActionBar;
private readonly _minimumHeight = 30;
private _editor: QueryTextEditor;
private _editorInput: UntitledEditorInput;
private _editorModel: ITextModel;
private _uri: string;
private _model: NotebookModel;
private _actions: Action[] = [];
private _activeCellId: string;
private _toggleMoreActions: NotebookCellToggleMoreActon;
constructor(
@Inject(forwardRef(() => CommonServiceInterface)) private _bootstrapService: CommonServiceInterface,
@@ -80,6 +81,13 @@ export class CodeComponent extends AngularDisposable implements OnInit, OnChange
@Inject(INotificationService) private notificationService: INotificationService,
) {
super();
this._actions.push(
this._instantiationService.createInstance(AddCellAction, 'codeBefore', localize('codeBefore', 'Insert Code before'), CellTypes.Code, false),
this._instantiationService.createInstance(AddCellAction, 'codeAfter', localize('codeAfter', 'Insert Code after'), CellTypes.Code, true),
this._instantiationService.createInstance(AddCellAction, 'markdownBefore', localize('markdownBefore', 'Insert Markdown before'), CellTypes.Markdown, false),
this._instantiationService.createInstance(AddCellAction, 'markdownAfter', localize('markdownAfter', 'Insert Markdown after'), CellTypes.Markdown, true),
this._instantiationService.createInstance(DeleteCellAction, 'delete', localize('delete', 'Delete'))
);
}
ngOnInit() {
@@ -90,20 +98,20 @@ export class CodeComponent extends AngularDisposable implements OnInit, OnChange
}
}
ngAfterViewInit() {
this._toggleMoreActions = new NotebookCellToggleMoreActon(
this._instantiationService,
this.contextMenuService,
this.notificationService,
this.moreActionsElementRef,
this.model);
}
ngOnChanges(changes: { [propKey: string]: SimpleChange }) {
this.updateLanguageMode();
this.updateModel();
if (this._toggleMoreActions) {
this._toggleMoreActions.onChange(this.cellModel, changes);
for (let propName in changes) {
if (propName === 'activeCellId') {
let changedProp = changes[propName];
if (this.cellModel.id === changedProp.currentValue) {
this.toggleMoreActions(true);
}
else {
this.toggleMoreActions(false);
}
break;
}
}
}
@@ -165,6 +173,21 @@ export class CodeComponent extends AngularDisposable implements OnInit, OnChange
]);
}
private toggleMoreActions(showIcon: boolean) {
let context = new CellContext(this.model, this.cellModel);
let moreActionsElement = <HTMLElement>this.moreActionsElementRef.nativeElement;
if (showIcon) {
if (moreActionsElement.childNodes.length > 0) {
moreActionsElement.removeChild(moreActionsElement.childNodes[0]);
}
this._moreActions = new ActionBar(moreActionsElement, { orientation: ActionsOrientation.VERTICAL });
this._moreActions.context = { target: moreActionsElement };
this._moreActions.push(this._instantiationService.createInstance(ToggleMoreWidgetAction, this._actions, context), { icon: showIcon, label: false });
}
else if (moreActionsElement.childNodes.length > 0) {
moreActionsElement.removeChild(moreActionsElement.childNodes[0]);
}
}
private createUri(): URI {
let uri = URI.from({ scheme: Schemas.untitled, path: `notebook-editor-${this.cellModel.id}` });
@@ -192,8 +215,8 @@ export class CodeComponent extends AngularDisposable implements OnInit, OnChange
let toolbarEl = <HTMLElement>this.toolbarElement.nativeElement;
toolbarEl.style.borderRightColor = theme.getColor(themeColors.SIDE_BAR_BACKGROUND, true).toString();
let moreactionsEl = <HTMLElement>this.moreActionsElementRef.nativeElement;
moreactionsEl.style.borderRightColor = theme.getColor(themeColors.SIDE_BAR_BACKGROUND, true).toString();
let moreActionsEl = <HTMLElement>this.moreActionsElementRef.nativeElement;
moreActionsEl.style.borderRightColor = theme.getColor(themeColors.SIDE_BAR_BACKGROUND, true).toString();
}
}

View File

@@ -5,20 +5,13 @@
import { nb } from 'sqlops';
import { ElementRef, SimpleChange } from '@angular/core';
import { Action } from 'vs/base/common/actions';
import { TPromise } from 'vs/base/common/winjs.base';
import { localize } from 'vs/nls';
import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
import { ToggleMoreWidgetAction } from 'sql/parts/dashboard/common/actions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { CellType, CellTypes } from 'sql/parts/notebook/models/contracts';
import { CellType } from 'sql/parts/notebook/models/contracts';
import { NotebookModel } from 'sql/parts/notebook/models/notebookModel';
import { getErrorMessage } from 'sql/parts/notebook/notebookUtils';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { ICellModel, FutureInternal } from 'sql/parts/notebook/models/modelInterfaces';
import { ToggleableAction } from 'sql/parts/notebook/notebookActions';
@@ -191,51 +184,4 @@ export class DeleteCellAction extends CellActionBase {
}
return Promise.resolve();
}
}
export class NotebookCellToggleMoreActon {
private _actions: Action[] = [];
private _moreActions: ActionBar;
constructor (
private _instantiationService: IInstantiationService,
private contextMenuService: IContextMenuService,
private notificationService: INotificationService,
private moreActionElementRef: ElementRef,
private model: NotebookModel
) {
this._actions.push(
this._instantiationService.createInstance(AddCellAction, 'codeBefore', localize('codeBefore', 'Insert Code before'), CellTypes.Code, false, this.notificationService),
this._instantiationService.createInstance(AddCellAction, 'codeBefore', localize('codeAfter', 'Insert Code after'), CellTypes.Code, true, this.notificationService),
this._instantiationService.createInstance(AddCellAction, 'markdownBefore', localize('markdownBefore', 'Insert Markdown before'), CellTypes.Markdown, false, this.notificationService),
this._instantiationService.createInstance(AddCellAction, 'markdownAfter', localize('markdownAfter', 'Insert Markdown after'), CellTypes.Markdown, true, this.notificationService),
this._instantiationService.createInstance(DeleteCellAction, 'delete', localize('delete', 'Delete'), this.notificationService)
);
let moreActionsElement = <HTMLElement>this.moreActionElementRef.nativeElement;
this._moreActions = new ActionBar(moreActionsElement, { orientation: ActionsOrientation.VERTICAL });
this._moreActions.context = { target: moreActionsElement };
}
toggle(showIcon: boolean): void {
if (showIcon) {
this._moreActions.push(this._instantiationService.createInstance(ToggleMoreWidgetAction, this._actions, this.model, this.contextMenuService), { icon: showIcon, label: false });
} else if (this._moreActions) {
this._moreActions.clear();
}
}
public onChange(cellModel: ICellModel, changes: { [propKey: string]: SimpleChange }): void {
for (let propName in changes) {
if (propName === 'activeCellId') {
let changedProp = changes[propName];
if (cellModel.id === changedProp.currentValue) {
this.toggle(true);
}
else {
this.toggle(false);
}
break;
}
}
}
}

View File

@@ -8,7 +8,7 @@
<div class="notebook-code" style="flex: 0 0 auto;">
<code-component [cellModel]="cellModel" [model]="model" [activeCellId]="activeCellId"></code-component>
</div>
<div #codeCellOutput class="notebook-output" style="flex: 0 0 auto;">
<div style="flex: 0 0 auto; width: 100%; height: 100%; display: block">
<output-area-component *ngIf="cellModel.outputs && cellModel.outputs.length > 0" [cellModel]="cellModel">
</output-area-component>
</div>

View File

@@ -2,15 +2,10 @@
* 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!./codeCell';
import { OnInit, Component, Input, Inject, forwardRef, ElementRef, ChangeDetectorRef, OnDestroy, ViewChild, SimpleChange, OnChanges } from '@angular/core';
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
import { CellView } from 'sql/parts/notebook/cellViews/interfaces';
import { IColorTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import * as themeColors from 'vs/workbench/common/theme';
import { ICellModel } from 'sql/parts/notebook/models/modelInterfaces';
import { NotebookModel } from 'sql/parts/notebook/models/notebookModel';
@@ -21,9 +16,9 @@ export const CODE_SELECTOR: string = 'code-cell-component';
selector: CODE_SELECTOR,
templateUrl: decodeURI(require.toUrl('./codeCell.component.html'))
})
export class CodeCellComponent extends CellView implements OnInit, OnChanges {
@ViewChild('codeCellOutput', { read: ElementRef }) private outputPreview: ElementRef;
@Input() cellModel: ICellModel;
@Input() set model(value: NotebookModel) {
this._model = value;
@@ -37,14 +32,11 @@ export class CodeCellComponent extends CellView implements OnInit, OnChanges {
constructor(
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeRef: ChangeDetectorRef,
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService
) {
super();
}
ngOnInit() {
this._register(this.themeService.onDidColorThemeChange(this.updateTheme, this));
this.updateTheme(this.themeService.getColorTheme());
if (this.cellModel) {
this.cellModel.onOutputsChanged(() => {
this._changeRef.detectChanges();
@@ -74,10 +66,4 @@ export class CodeCellComponent extends CellView implements OnInit, OnChanges {
public layout() {
}
private updateTheme(theme: IColorTheme): void {
let outputElement = <HTMLElement>this.outputPreview.nativeElement;
outputElement.style.borderTopColor = theme.getColor(themeColors.SIDE_BAR_BACKGROUND, true).toString();
}
}

View File

@@ -5,7 +5,7 @@
*--------------------------------------------------------------------------------------------*/
-->
<div style="overflow: hidden; width: 100%; height: 100%; display: flex; flex-flow: column">
<div style="flex: 0 0 auto;">
<div #outputarea class="notebook-output" style="flex: 0 0 auto;">
<output-component *ngFor="let output of cellModel.outputs" [cellOutput]="output" [trustedMode] = "cellModel.trustedMode" >
</output-component>
</div>

View File

@@ -3,9 +3,12 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./code';
import { OnInit, Component, Input, Inject, forwardRef, ChangeDetectorRef } from '@angular/core';
import 'vs/css!./outputArea';
import { OnInit, Component, Input, Inject, ElementRef, ViewChild, forwardRef, ChangeDetectorRef } from '@angular/core';
import { AngularDisposable } from 'sql/base/common/lifecycle';
import { ICellModel } from 'sql/parts/notebook/models/modelInterfaces';
import * as themeColors from 'vs/workbench/common/theme';
import { IWorkbenchThemeService, IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeService';
export const OUTPUT_AREA_SELECTOR: string = 'output-area-component';
@@ -14,20 +17,30 @@ export const OUTPUT_AREA_SELECTOR: string = 'output-area-component';
templateUrl: decodeURI(require.toUrl('./outputArea.component.html'))
})
export class OutputAreaComponent extends AngularDisposable implements OnInit {
@ViewChild('outputarea', { read: ElementRef }) private outputArea: ElementRef;
@Input() cellModel: ICellModel;
private readonly _minimumHeight = 30;
constructor(
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeRef: ChangeDetectorRef,
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService,
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeRef: ChangeDetectorRef
) {
super();
}
ngOnInit(): void {
ngOnInit() {
this._register(this.themeService.onDidColorThemeChange(this.updateTheme, this));
this.updateTheme(this.themeService.getColorTheme());
if (this.cellModel) {
this.cellModel.onOutputsChanged(() => {
this._changeRef.detectChanges();
});
}
}
private updateTheme(theme: IColorTheme): void {
let outputElement = <HTMLElement>this.outputArea.nativeElement;
outputElement.style.borderTopColor = theme.getColor(themeColors.SIDE_BAR_BACKGROUND, true).toString();
}
}

View File

@@ -2,13 +2,14 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
code-cell-component {
output-area-component {
display: block;
}
code-cell-component .notebook-output {
output-area-component .notebook-output {
border-top-width: 1px;
border-top-style: solid;
user-select: initial;
padding: 5px 20px 0px;
box-shadow: rgba(120, 120, 120, 0.75) 0px -2px 1px -2px;
}

View File

@@ -6,8 +6,9 @@
-->
<div style="overflow: hidden; width: 100%; height: 100%; display: flex; flex-flow: column">
<div class="notebook-text" style="flex: 0 0 auto;">
<code-component *ngIf="isEditMode" [cellModel]="cellModel" (onContentChanged)="handleContentChanged()" [activeCellId]="activeCellId" [hideVerticalToolbar]=1></code-component>
<code-component *ngIf="isEditMode" [cellModel]="cellModel" (onContentChanged)="handleContentChanged()" [model]="model" [activeCellId]="activeCellId" [hideVerticalToolbar]=true>
</code-component>
</div>
<div #preview class="notebook-preview" style="flex: 0 0 auto;" (dblclick)="toggleEditMode()">
<div #preview style="flex: 0 0 auto;" (dblclick)="toggleEditMode()">
</div>
</div>

View File

@@ -15,6 +15,7 @@ import { ICommandService } from 'vs/platform/commands/common/commands';
import { ICellModel } from 'sql/parts/notebook/models/modelInterfaces';
import { ISanitizer, defaultSanitizer } from 'sql/parts/notebook/outputs/sanitizer';
import { localize } from 'vs/nls';
import { NotebookModel } from 'sql/parts/notebook/models/notebookModel';
export const TEXT_SELECTOR: string = 'text-cell-component';
@@ -25,12 +26,20 @@ export const TEXT_SELECTOR: string = 'text-cell-component';
export class TextCellComponent extends CellView implements OnInit, OnChanges {
@ViewChild('preview', { read: ElementRef }) private output: ElementRef;
@Input() cellModel: ICellModel;
@Input() set model(value: NotebookModel) {
this._model = value;
}
@Input() set activeCellId(value: string) {
this._activeCellId = value;
}
private _content: string;
private isEditMode: boolean;
private _sanitizer: ISanitizer;
private _previewCssApplied: boolean = false;
private _model: NotebookModel;
private _activeCellId: string;
constructor(
@@ -43,17 +52,6 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
this.isEditMode = false;
}
ngOnChanges(changes: { [propKey: string]: SimpleChange }) {
this.updatePreview();
for (let propName in changes) {
if (propName === 'activeCellId') {
let changedProp = changes[propName];
this._activeCellId = changedProp.currentValue;
break;
}
}
}
//Gets sanitizer from ISanitizer interface
private get sanitizer(): ISanitizer {
if (this._sanitizer) {
@@ -62,17 +60,43 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
return this._sanitizer = defaultSanitizer;
}
get model(): NotebookModel {
return this._model;
}
get activeCellId(): string {
return this._activeCellId;
}
ngOnInit() {
this.updatePreview();
this._register(this.themeService.onDidColorThemeChange(this.updateTheme, this));
this.updateTheme(this.themeService.getColorTheme());
this.cellModel.onOutputsChanged(e => {
this.updatePreview();
});
}
ngOnChanges(changes: { [propKey: string]: SimpleChange }) {
for (let propName in changes) {
if (propName === 'activeCellId') {
let changedProp = changes[propName];
this._activeCellId = changedProp.currentValue;
if (this._activeCellId) {
this.toggleEditMode(false);
}
break;
}
}
}
/**
* Updates the preview of markdown component with latest changes
* If content is empty and in non-edit mode, default it to 'Double-click to edit'
* Sanitizes the data to be shown in markdown cell
*/
private updatePreview() {
if (this._content !== this.cellModel.source) {
if (this._content !== this.cellModel.source || this.cellModel.source.length === 0) {
if (!this.cellModel.source && !this.isEditMode) {
(<HTMLElement>this.output.nativeElement).innerHTML = localize('doubleClickEdit', 'Double-click to edit');
} else {
@@ -93,15 +117,7 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
}
return content;
}
ngOnInit() {
this.updatePreview();
this._register(this.themeService.onDidColorThemeChange(this.updateTheme, this));
this.updateTheme(this.themeService.getColorTheme());
this.cellModel.onOutputsChanged(e => {
this.updatePreview();
});
}
// Todo: implement layout
public layout() {
@@ -113,12 +129,29 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
}
public handleContentChanged(): void {
if (!this._previewCssApplied) {
this.updatePreviewCssClass();
}
this.updatePreview();
}
public toggleEditMode(): void {
this.isEditMode = !this.isEditMode;
public toggleEditMode(editMode?: boolean): void {
this.isEditMode = editMode !== undefined? editMode : !this.isEditMode;
this.updatePreviewCssClass();
this.updatePreview();
this._changeRef.detectChanges();
}
// Updates the css class to preview 'div' based on edit mode
private updatePreviewCssClass() {
let outputElement = <HTMLElement>this.output.nativeElement;
if (this.isEditMode && this.cellModel.source) {
outputElement.className = 'notebook-preview';
this._previewCssApplied = true;
}
else {
outputElement.className = '';
this._previewCssApplied = false;
}
}
}

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>save_inverse</title><path class="cls-1" d="M14,1a1,1,0,0,1,.39.08,1,1,0,0,1,.53.53A1,1,0,0,1,15,2V15H2.79L1,13.2V2a1,1,0,0,1,.08-.39,1,1,0,0,1,.53-.53A1,1,0,0,1,2,1Zm0,1H13V8H3V2H2V12.79L3.2,14H4V10h7v4h3ZM4,7h8V2H4Zm6,4H5v3H6V12H7v2h3Z"/></svg>

After

Width:  |  Height:  |  Size: 391 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"><title>save</title><path d="M14,1a1,1,0,0,1,.39.08,1,1,0,0,1,.53.53A1,1,0,0,1,15,2V15H2.79L1,13.2V2a1,1,0,0,1,.08-.39,1,1,0,0,1,.53-.53A1,1,0,0,1,2,1Zm0,1H13V8H3V2H2V12.79L3.2,14H4V10h7v4h3ZM4,7h8V2H4Zm6,4H5v3H6V12H7v2h3Z"/></svg>

After

Width:  |  Height:  |  Size: 323 B

View File

@@ -14,6 +14,7 @@ import { ICellModelOptions, IModelFactory, FutureInternal } from './modelInterfa
import * as notebookUtils from '../notebookUtils';
import { CellTypes, CellType, NotebookChangeType } from 'sql/parts/notebook/models/contracts';
import { ICellModel } from 'sql/parts/notebook/models/modelInterfaces';
import { NotebookModel } from 'sql/parts/notebook/models/notebookModel';
let modelId = 0;
@@ -222,11 +223,41 @@ export class CellModel implements ICellModel {
if (output) {
// deletes transient node in the serialized JSON
delete output['transient'];
this._outputs.push(output);
this._outputs.push(this.rewriteOutputUrls(output));
this.fireOutputsChanged();
}
}
private rewriteOutputUrls(output: nb.ICellOutput): nb.ICellOutput {
// Only rewrite if this is coming back during execution, not when loading from disk.
// A good approximation is that the model has a future (needed for execution)
if (this.future) {
try {
let result = output as nb.IDisplayResult;
if (result && result.data && result.data['text/html']) {
let nbm = (this as CellModel).options.notebook as NotebookModel;
if (nbm.hadoopConnection) {
let host = nbm.hadoopConnection.host;
let html = result.data['text/html'];
html = html.replace(/(https?:\/\/mssql-master.*\/proxy)(.*)/g, function (a, b, c) {
let ret = '';
if (b !== '') {
ret = 'https://' + host + ':30443/gateway/default/yarn/proxy';
}
if (c !== '') {
ret = ret + c;
}
return ret;
});
(<nb.IDisplayResult>output).data['text/html'] = html;
}
}
}
catch (e) {}
}
return output;
}
private getDisplayId(msg: nb.IIOPubMessage): string | undefined {
let transient = (msg.content.transient || {});
return transient['display_id'] as string;

View File

@@ -12,7 +12,7 @@
<div class="notebook-cell" *ngFor="let cell of cells" (click)="selectCell(cell)" [class.active]="cell.active" (keydown)="onKeyDown($event)">
<code-cell-component *ngIf="cell.cellType === 'code'" [cellModel]="cell" [model]="model" [activeCellId]="activeCellId">
</code-cell-component>
<text-cell-component *ngIf="cell.cellType === 'markdown'" [cellModel]="cell" [activeCellId]="activeCellId">
<text-cell-component *ngIf="cell.cellType === 'markdown'" [cellModel]="cell" [model]="model" [activeCellId]="activeCellId">
</text-cell-component>
</div>
</div>

View File

@@ -31,7 +31,7 @@ import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { KernelsDropdown, AttachToDropdown, AddCellAction, TrustedAction } from 'sql/parts/notebook/notebookActions';
import { KernelsDropdown, AttachToDropdown, AddCellAction, TrustedAction, SaveNotebookAction } from 'sql/parts/notebook/notebookActions';
import { attachSelectBoxStyler } from 'vs/platform/theme/common/styler';
export const NOTEBOOK_SELECTOR: string = 'notebook-component';
@@ -239,9 +239,6 @@ export class NotebookComponent extends AngularDisposable implements OnInit {
attachTodropdwon.render(attachToContainer);
attachSelectBoxStyler(attachTodropdwon, this.themeService);
let attachToInfoText = document.createElement('div');
attachToInfoText.className = 'notebook-info-label';
attachToInfoText.innerText = 'Attach To: ';
let addCodeCellButton = new AddCellAction('notebook.AddCodeCell', localize('code', 'Code'), 'notebook-button icon-add');
addCodeCellButton.cellType = CellTypes.Code;
@@ -252,15 +249,18 @@ export class NotebookComponent extends AngularDisposable implements OnInit {
this._trustedAction = this.instantiationService.createInstance(TrustedAction, 'notebook.Trusted');
this._trustedAction.enabled = false;
let saveNotebookButton = this.instantiationService.createInstance(SaveNotebookAction, 'notebook.SaveNotebook', localize('save', 'Save'), 'notebook-button icon-save');
let taskbar = <HTMLElement>this.toolbar.nativeElement;
this._actionBar = new Taskbar(taskbar, this.contextMenuService);
this._actionBar.context = this;
this._actionBar.setContent([
{ element: kernelContainer },
{ element: attachToContainer },
{ action: addCodeCellButton},
{ action: addTextCellButton},
{ action: this._trustedAction}
{ action: addCodeCellButton },
{ action: addTextCellButton },
{ action: saveNotebookButton },
{ action: this._trustedAction }
]);
}

View File

@@ -31,9 +31,9 @@
text-align: center;
cursor: pointer;
padding-left: 15px;
background-size: 11px;
background-size: 13px;
margin-right: 0.3em;
font-size: 11px;
font-size: 13px;
}
.notebookEditor .notebook-button.icon-add{
@@ -61,4 +61,13 @@
.vs-dark .notebookEditor .notebook-button.icon-notTrusted,
.hc-black .notebookEditor .notebook-button.icon-notTrusted{
background-image: url("./media/dark/nottrusted_inverse.svg");
}
.notebookEditor .notebook-button.icon-save{
background-image: url("./media/light/save.svg");
}
.vs-dark .notebookEditor .notebook-button.icon-save,
.hc-black .notebookEditor .notebook-button.icon-save{
background-image: url("./media/dark/save_inverse.svg");
}

View File

@@ -26,6 +26,7 @@ const msgLoadingContexts = localize('loadingContexts', 'Loading contexts...');
const msgAddNewConnection = localize('addNewConnection', 'Add new connection');
const msgSelectConnection = localize('selectConnection', 'Select connection');
const msgConnectionNotApplicable = localize('connectionNotSupported', 'n/a');
const msgLocalHost = localize('localhost', 'Localhost');
// Action to add a cell to notebook based on cell type(code/markdown).
export class AddCellAction extends Action {
@@ -48,6 +49,28 @@ export class AddCellAction extends Action {
}
}
export class SaveNotebookAction extends Action {
private static readonly notebookSavedMsg = localize('notebookSavedMsg', 'Notebook saved successfully.');
private static readonly notebookFailedSaveMsg = localize('notebookFailedSaveMsg', 'Failed to save Notebook.');
constructor(
id: string, label: string, cssClass: string,
@INotificationService private _notificationService: INotificationService
) {
super(id, label, cssClass);
}
public async run(context: NotebookComponent): TPromise<boolean> {
const actions: INotificationActions = { primary: [] };
let saved = await context.save();
if (saved) {
this._notificationService.notify({ severity: Severity.Info, message: SaveNotebookAction.notebookSavedMsg, actions });
} else {
this._notificationService.error(SaveNotebookAction.notebookFailedSaveMsg);
}
return saved;
}
}
export interface IToggleableState {
baseClass?: string;
shouldToggleTooltip?: boolean;
@@ -216,8 +239,7 @@ export class AttachToDropdown extends SelectBox {
// Load "Attach To" dropdown with the values corresponding to Kernel dropdown
public async loadAttachToDropdown(model: INotebookModel, currentKernel: string): Promise<void> {
if (currentKernel === notebookConstants.python3) {
this.setOptions([msgConnectionNotApplicable]);
this.disable();
this.setOptions([msgLocalHost]);
}
else {
let hadoopConnections = this.getHadoopConnections(model);

View File

@@ -29,7 +29,7 @@ export interface IQueryManagementService {
runQueryStatement(ownerUri: string, line: number, column: number): Thenable<void>;
runQueryString(ownerUri: string, queryString: string): Thenable<void>;
runQueryAndReturn(ownerUri: string, queryString: string): Thenable<sqlops.SimpleExecuteResult>;
parseSyntax(ownerUri:string, query: string): Thenable<sqlops.SyntaxParseResult>;
parseSyntax(ownerUri: string, query: string): Thenable<sqlops.SyntaxParseResult>;
getQueryRows(rowData: sqlops.QueryExecuteSubsetParams): Thenable<sqlops.QueryExecuteSubsetResult>;
disposeQuery(ownerUri: string): Thenable<void>;
saveResults(requestParams: sqlops.SaveResultsRequestParams): Thenable<sqlops.SaveResultRequestResult>;
@@ -38,7 +38,8 @@ export interface IQueryManagementService {
onQueryComplete(result: sqlops.QueryExecuteCompleteNotificationResult): void;
onBatchStart(batchInfo: sqlops.QueryExecuteBatchNotificationParams): void;
onBatchComplete(batchInfo: sqlops.QueryExecuteBatchNotificationParams): void;
onResultSetComplete(resultSetInfo: sqlops.QueryExecuteResultSetCompleteNotificationParams): void;
onResultSetAvailable(resultSetInfo: sqlops.QueryExecuteResultSetNotificationParams): void;
onResultSetUpdated(resultSetInfo: sqlops.QueryExecuteResultSetNotificationParams): void;
onMessage(message: sqlops.QueryExecuteMessageParams): void;
// Edit Data Callbacks
@@ -65,7 +66,7 @@ export interface IQueryRequestHandler {
runQueryStatement(ownerUri: string, line: number, column: number): Thenable<void>;
runQueryString(ownerUri: string, queryString: string): Thenable<void>;
runQueryAndReturn(ownerUri: string, queryString: string): Thenable<sqlops.SimpleExecuteResult>;
parseSyntax(ownerUri:string, query: string): Thenable<sqlops.SyntaxParseResult>;
parseSyntax(ownerUri: string, query: string): Thenable<sqlops.SyntaxParseResult>;
getQueryRows(rowData: sqlops.QueryExecuteSubsetParams): Thenable<sqlops.QueryExecuteSubsetResult>;
disposeQuery(ownerUri: string): Thenable<void>;
saveResults(requestParams: sqlops.SaveResultsRequestParams): Thenable<sqlops.SaveResultRequestResult>;
@@ -244,9 +245,15 @@ export class QueryManagementService implements IQueryManagementService {
});
}
public onResultSetComplete(resultSetInfo: sqlops.QueryExecuteResultSetCompleteNotificationParams): void {
public onResultSetAvailable(resultSetInfo: sqlops.QueryExecuteResultSetNotificationParams): void {
this._notify(resultSetInfo.ownerUri, (runner: QueryRunner) => {
runner.handleResultSetComplete(resultSetInfo);
runner.handleResultSetAvailable(resultSetInfo);
});
}
public onResultSetUpdated(resultSetInfo: sqlops.QueryExecuteResultSetNotificationParams): void {
this._notify(resultSetInfo.ownerUri, (runner: QueryRunner) => {
runner.handleResultSetUpdated(resultSetInfo);
});
}

View File

@@ -4,6 +4,8 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as pretty from 'pretty-data';
import { attachTableStyler } from 'sql/common/theme/styler';
import QueryRunner from 'sql/parts/query/execution/queryRunner';
import { VirtualizedCollection, AsyncDataProvider } from 'sql/base/browser/ui/table/asyncDataView';
@@ -12,7 +14,7 @@ import { ScrollableSplitView } from 'sql/base/browser/ui/scrollableSplitview/scr
import { MouseWheelSupport } from 'sql/base/browser/ui/table/plugins/mousewheelTableScroll.plugin';
import { AutoColumnSize } from 'sql/base/browser/ui/table/plugins/autoSizeColumns.plugin';
import { SaveFormat } from 'sql/parts/grid/common/interfaces';
import { IGridActionContext, SaveResultAction, CopyResultAction, SelectAllGridAction, MaximizeTableAction, RestoreTableAction, ChartDataAction, ShowQueryPlanAction } from 'sql/parts/query/editor/actions';
import { IGridActionContext, SaveResultAction, CopyResultAction, SelectAllGridAction, MaximizeTableAction, RestoreTableAction, ChartDataAction } from 'sql/parts/query/editor/actions';
import { CellSelectionModel } from 'sql/base/browser/ui/table/plugins/cellSelectionModel.plugin';
import { RowNumberColumn } from 'sql/base/browser/ui/table/plugins/rowNumberColumn.plugin';
import { escape } from 'sql/base/common/strings';
@@ -20,9 +22,9 @@ import { hyperLinkFormatter, textFormatter } from 'sql/parts/grid/services/share
import { CopyKeybind } from 'sql/base/browser/ui/table/plugins/copyKeybind.plugin';
import { AdditionalKeyBindings } from 'sql/base/browser/ui/table/plugins/additionalKeyBindings.plugin';
import { ITableStyles, ITableMouseEvent } from 'sql/base/browser/ui/table/interfaces';
import { warn } from 'sql/base/common/log';
import * as sqlops from 'sqlops';
import * as pretty from 'pretty-data';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
@@ -38,7 +40,7 @@ import { $ } from 'vs/base/browser/builder';
import { generateUuid } from 'vs/base/common/uuid';
import { TPromise } from 'vs/base/common/winjs.base';
import { Separator, ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
import { Dimension, getContentWidth, isInDOM } from 'vs/base/browser/dom';
import { isInDOM } from 'vs/base/browser/dom';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
@@ -175,7 +177,8 @@ export class GridPanel extends ViewletPanel {
this.reset();
this.queryRunnerDisposables = [];
this.runner = runner;
this.queryRunnerDisposables.push(this.runner.onResultSet(e => this.onResultSet(e)));
this.queryRunnerDisposables.push(this.runner.onResultSet(this.onResultSet, this));
this.queryRunnerDisposables.push(this.runner.onResultSetUpdate(this.updateResultSet, this));
this.queryRunnerDisposables.push(this.runner.onQueryStart(() => {
if (this.state) {
this.state.tableStates = [];
@@ -200,6 +203,33 @@ export class GridPanel extends ViewletPanel {
}
}
private updateResultSet(resultSet: sqlops.ResultSetSummary | sqlops.ResultSetSummary[]) {
let resultsToUpdate: sqlops.ResultSetSummary[];
if (!Array.isArray(resultSet)) {
resultsToUpdate = [resultSet];
} else {
resultsToUpdate = resultSet;
}
for (let set of resultsToUpdate) {
let table = this.tables.find(t => t.resultSet.batchId === set.batchId && t.resultSet.id === set.id);
if (table) {
table.updateResult(set);
} else {
warn('Got result set update request for non-existant table');
}
}
this.maximumBodySize = this.tables.reduce((p, c) => {
return p + c.maximumSize;
}, 0);
if (this.state && this.state.scrollPosition) {
this.splitView.setScrollPosition(this.state.scrollPosition);
}
}
private addResultSet(resultSet: sqlops.ResultSetSummary | sqlops.ResultSetSummary[]) {
let resultsToAdd: sqlops.ResultSetSummary[];
if (!Array.isArray(resultSet)) {
@@ -323,9 +353,12 @@ class GridTable<T> extends Disposable implements IView {
private selectionModel = new CellSelectionModel();
private styles: ITableStyles;
private currentHeight: number;
private dataProvider: AsyncDataProvider<T>;
private columns: Slick.Column<T>[];
private rowNumberColumn: RowNumberColumn<T>;
private _onDidChange = new Emitter<number>();
public readonly onDidChange: Event<number> = this._onDidChange.event;
@@ -335,13 +368,20 @@ class GridTable<T> extends Disposable implements IView {
private _state: GridTableState;
private scrolled = false;
private visible = false;
public get resultSet(): sqlops.ResultSetSummary {
return this._resultSet;
}
// this handles if the row count is small, like 4-5 rows
private readonly maxSize = ((this.resultSet.rowCount) * ROW_HEIGHT) + HEADER_HEIGHT + ESTIMATED_SCROLL_BAR_HEIGHT;
private get maxSize(): number {
return ((this.resultSet.rowCount) * ROW_HEIGHT) + HEADER_HEIGHT + ESTIMATED_SCROLL_BAR_HEIGHT;
}
constructor(
private runner: QueryRunner,
public readonly resultSet: sqlops.ResultSetSummary,
private _resultSet: sqlops.ResultSetSummary,
@IContextMenuService private contextMenuService: IContextMenuService,
@IInstantiationService private instantiationService: IInstantiationService,
@IEditorService private editorService: IEditorService,
@@ -367,7 +407,31 @@ class GridTable<T> extends Disposable implements IView {
});
}
public onAdd() {
this.visible = true;
let collection = new VirtualizedCollection(
50,
index => this.placeholdGenerator(index),
this.resultSet.rowCount,
(offset, count) => this.loadData(offset, count)
);
collection.setCollectionChangedCallback((startIndex, count) => {
this.renderGridDataRowsRange(startIndex, count);
});
this.dataProvider.dataRows = collection;
this.table.updateRowCount();
}
public onRemove() {
this.visible = false;
let collection = new VirtualizedCollection(
50,
index => this.placeholdGenerator(index),
0,
() => TPromise.as([])
);
this.dataProvider.dataRows = collection;
this.table.updateRowCount();
// when we are removed slickgrid acts badly so we need to account for that
this.scrolled = false;
}
@@ -379,34 +443,38 @@ class GridTable<T> extends Disposable implements IView {
private build(): void {
let tableContainer = document.createElement('div');
tableContainer.style.display = 'inline-block';
tableContainer.style.width = `calc(100% - ${ACTIONBAR_WIDTH}px)`;
this.container.appendChild(tableContainer);
let collection = new VirtualizedCollection(50, this.resultSet.rowCount,
(offset, count) => this.loadData(offset, count),
index => this.placeholdGenerator(index)
let collection = new VirtualizedCollection(
50,
index => this.placeholdGenerator(index),
0,
() => TPromise.as([])
);
collection.setCollectionChangedCallback((change, startIndex, count) => {
collection.setCollectionChangedCallback((startIndex, count) => {
this.renderGridDataRowsRange(startIndex, count);
});
let numberColumn = new RowNumberColumn({ numberOfRows: this.resultSet.rowCount });
this.rowNumberColumn = new RowNumberColumn({ numberOfRows: this.resultSet.rowCount });
let copyHandler = new CopyKeybind();
copyHandler.onCopy(e => {
new CopyResultAction(CopyResultAction.COPY_ID, CopyResultAction.COPY_LABEL, false).run(this.generateContext());
});
this.columns.unshift(numberColumn.getColumnDefinition());
this.columns.unshift(this.rowNumberColumn.getColumnDefinition());
let tableOptions: Slick.GridOptions<T> = {
rowHeight: ROW_HEIGHT,
showRowNumber: true,
forceFitColumns: false,
defaultColumnWidth: 120
};
this.table = this._register(new Table(tableContainer, { dataProvider: new AsyncDataProvider(collection), columns: this.columns }, tableOptions));
this.dataProvider = new AsyncDataProvider(collection);
this.table = this._register(new Table(tableContainer, { dataProvider: this.dataProvider, columns: this.columns }, tableOptions));
this.table.setSelectionModel(this.selectionModel);
this.table.registerPlugin(new MouseWheelSupport());
this.table.registerPlugin(new AutoColumnSize());
this.table.registerPlugin(copyHandler);
this.table.registerPlugin(numberColumn);
this.table.registerPlugin(this.rowNumberColumn);
this.table.registerPlugin(new AdditionalKeyBindings());
this._register(this.table.onContextMenu(this.contextMenu, this));
this._register(this.table.onClick(this.onTableClick, this));
@@ -507,7 +575,7 @@ class GridTable<T> extends Disposable implements IView {
} catch (e) {
// If Xml fails to parse, fall back on original Xml content
}
} else {
} else {
let jsonContent: string = undefined;
try {
jsonContent = JSON.parse(content);
@@ -526,6 +594,15 @@ class GridTable<T> extends Disposable implements IView {
}
}
public updateResult(resultSet: sqlops.ResultSetSummary) {
this._resultSet = resultSet;
if (this.table && this.visible) {
this.dataProvider.length = resultSet.rowCount;
this.table.updateRowCount();
}
this.rowNumberColumn.updateRowCount(resultSet.rowCount);
}
private generateContext(cell?: Slick.Cell): IGridActionContext {
const selection = this.selectionModel.getSelectedRanges();
return <IGridActionContext>{
@@ -577,12 +654,7 @@ class GridTable<T> extends Disposable implements IView {
} else {
this.currentHeight = size;
}
this.table.layout(
new Dimension(
getContentWidth(this.container) - ACTIONBAR_WIDTH,
size
)
);
this.table.layout(size, Orientation.VERTICAL);
}
public get minimumSize(): number {
@@ -596,6 +668,9 @@ class GridTable<T> extends Disposable implements IView {
private loadData(offset: number, count: number): Thenable<T[]> {
return this.runner.getQueryRows(offset, count, this.resultSet.batchId, this.resultSet.id).then(response => {
if (!response.resultSubset) {
return [];
}
return response.resultSubset.rows.map(r => {
let dataWithSchema = {};
// skip the first column since its a number column

View File

@@ -100,6 +100,18 @@ export default class QueryRunner extends Disposable {
private _echoedResultSet = echo(this._debouncedResultSet.event);
public readonly onResultSet = this._echoedResultSet.event;
private _onResultSetUpdate = this._register(new Emitter<sqlops.ResultSetSummary>());
private _debouncedResultSetUpdate = debounceEvent<sqlops.ResultSetSummary, sqlops.ResultSetSummary[]>(this._onResultSetUpdate.event, (l, e) => {
// on first run
if (types.isUndefinedOrNull(l)) {
return [e];
} else {
return l.concat(e);
}
});
private _echoedResultSetUpdate = echo(this._debouncedResultSetUpdate.event);
public readonly onResultSetUpdate = this._echoedResultSetUpdate.event;
private _onQueryStart = this._register(new Emitter<void>());
public readonly onQueryStart: Event<void> = this._onQueryStart.event;
@@ -336,7 +348,7 @@ export default class QueryRunner extends Disposable {
/**
* Handle a ResultSetComplete from the service layer
*/
public handleResultSetComplete(result: sqlops.QueryExecuteResultSetCompleteNotificationParams): void {
public handleResultSetAvailable(result: sqlops.QueryExecuteResultSetNotificationParams): void {
if (result && result.resultSetSummary) {
let resultSet = result.resultSetSummary;
let batchSet: sqlops.BatchSummary;
@@ -365,7 +377,9 @@ export default class QueryRunner extends Disposable {
this.getQueryRows(0, 1, result.resultSetSummary.batchId, result.resultSetSummary.id).then(e => this._planXml.resolve(e.resultSubset.rows[0][0].displayValue));
}
}
if (batchSet) {
// we will just ignore the set if we already have it
// ideally this should never happen
if (batchSet && !batchSet.resultSetSummaries[resultSet.id]) {
// Store the result set in the batch and emit that a result set has completed
batchSet.resultSetSummaries[resultSet.id] = resultSet;
this._eventEmitter.emit(EventType.RESULT_SET, resultSet);
@@ -374,6 +388,27 @@ export default class QueryRunner extends Disposable {
}
}
public handleResultSetUpdated(result: sqlops.QueryExecuteResultSetNotificationParams): void {
if (result && result.resultSetSummary) {
let resultSet = result.resultSetSummary;
let batchSet: sqlops.BatchSummary;
batchSet = this.batchSets[resultSet.batchId];
// handle getting queryPlanxml if we need too
if (this.isQueryPlan) {
// check if this result has show plan, this needs work, it won't work for any other provider
let hasShowPlan = !!result.resultSetSummary.columnInfo.find(e => e.columnName === 'Microsoft SQL Server 2005 XML Showplan');
if (hasShowPlan) {
this.getQueryRows(0, 1, result.resultSetSummary.batchId, result.resultSetSummary.id).then(e => this._planXml.resolve(e.resultSubset.rows[0][0].displayValue));
}
}
if (batchSet) {
// Store the result set in the batch and emit that a result set has completed
batchSet.resultSetSummaries[resultSet.id] = resultSet;
this._onResultSetUpdate.fire(resultSet);
}
}
}
/**
* Handle a Mssage from the service layer
*/

View File

@@ -249,9 +249,9 @@ export class QueryEditorService implements IQueryEditorService {
QueryEditorService.editorService.openEditor(newEditorInput, options, group).then((editor) => {
resolve(QueryEditorService._onEditorOpened(editor, uri.toString(), undefined, options.pinned));
},
(error) => {
reject(error);
});
(error) => {
reject(error);
});
});
});
}

6
src/sql/sqlops.d.ts vendored
View File

@@ -694,7 +694,8 @@ declare module 'sqlops' {
registerOnQueryComplete(handler: (result: QueryExecuteCompleteNotificationResult) => any): void;
registerOnBatchStart(handler: (batchInfo: QueryExecuteBatchNotificationParams) => any): void;
registerOnBatchComplete(handler: (batchInfo: QueryExecuteBatchNotificationParams) => any): void;
registerOnResultSetComplete(handler: (resultSetInfo: QueryExecuteResultSetCompleteNotificationParams) => any): void;
registerOnResultSetAvailable(handler: (resultSetInfo: QueryExecuteResultSetNotificationParams) => any): void;
registerOnResultSetUpdated(handler: (resultSetInfo: QueryExecuteResultSetNotificationParams) => any): void;
registerOnMessage(handler: (message: QueryExecuteMessageParams) => any): void;
// Edit Data Requests
@@ -769,6 +770,7 @@ declare module 'sqlops' {
batchId: number;
rowCount: number;
columnInfo: IDbColumn[];
complete: boolean;
}
export interface BatchSummary {
@@ -837,7 +839,7 @@ declare module 'sqlops' {
}
export interface QueryExecuteResultSetCompleteNotificationParams {
export interface QueryExecuteResultSetNotificationParams {
resultSetSummary: ResultSetSummary;
ownerUri: string;
}

View File

@@ -265,8 +265,11 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape {
$onBatchComplete(handle: number, batchInfo: sqlops.QueryExecuteBatchNotificationParams): void {
this._proxy.$onBatchComplete(handle, batchInfo);
}
$onResultSetComplete(handle: number, resultSetInfo: sqlops.QueryExecuteResultSetCompleteNotificationParams): void {
this._proxy.$onResultSetComplete(handle, resultSetInfo);
$onResultSetAvailable(handle: number, resultSetInfo: sqlops.QueryExecuteResultSetNotificationParams): void {
this._proxy.$onResultSetAvailable(handle, resultSetInfo);
}
$onResultSetUpdated(handle: number, resultSetInfo: sqlops.QueryExecuteResultSetNotificationParams): void {
this._proxy.$onResultSetUpdated(handle, resultSetInfo);
}
$onQueryMessage(handle: number, message: sqlops.QueryExecuteMessageParams): void {
this._proxy.$onQueryMessage(handle, message);

View File

@@ -444,8 +444,11 @@ export class MainThreadDataProtocol implements MainThreadDataProtocolShape {
public $onBatchComplete(handle: number, batchInfo: sqlops.QueryExecuteBatchNotificationParams): void {
this._queryManagementService.onBatchComplete(batchInfo);
}
public $onResultSetComplete(handle: number, resultSetInfo: sqlops.QueryExecuteResultSetCompleteNotificationParams): void {
this._queryManagementService.onResultSetComplete(resultSetInfo);
public $onResultSetAvailable(handle: number, resultSetInfo: sqlops.QueryExecuteResultSetNotificationParams): void {
this._queryManagementService.onResultSetAvailable(resultSetInfo);
}
public $onResultSetUpdated(handle: number, resultSetInfo: sqlops.QueryExecuteResultSetNotificationParams): void {
this._queryManagementService.onResultSetUpdated(resultSetInfo);
}
public $onQueryMessage(handle: number, message: sqlops.QueryExecuteMessageParams): void {
this._queryManagementService.onMessage(message);

View File

@@ -197,8 +197,12 @@ export function createApiFactory(
extHostDataProvider.$onBatchComplete(provider.handle, batchInfo);
});
provider.registerOnResultSetComplete((resultSetInfo: sqlops.QueryExecuteResultSetCompleteNotificationParams) => {
extHostDataProvider.$onResultSetComplete(provider.handle, resultSetInfo);
provider.registerOnResultSetAvailable((resultSetInfo: sqlops.QueryExecuteResultSetNotificationParams) => {
extHostDataProvider.$onResultSetAvailable(provider.handle, resultSetInfo);
});
provider.registerOnResultSetUpdated((resultSetInfo: sqlops.QueryExecuteResultSetNotificationParams) => {
extHostDataProvider.$onResultSetUpdated(provider.handle, resultSetInfo);
});
provider.registerOnMessage((message: sqlops.QueryExecuteMessageParams) => {

View File

@@ -193,7 +193,11 @@ export abstract class ExtHostDataProtocolShape {
/**
* Callback when a result set has been returned from query execution and can be displayed
*/
$onResultSetComplete(handle: number, resultSetInfo: sqlops.QueryExecuteResultSetCompleteNotificationParams): void { throw ni(); }
$onResultSetAvailable(handle: number, resultSetInfo: sqlops.QueryExecuteResultSetNotificationParams): void { throw ni(); }
/**
* Callback when a result set has been returned from query execution and can be displayed
*/
$onResultSetUpdate(handle: number, resultSetInfo: sqlops.QueryExecuteResultSetNotificationParams): void { throw ni(); }
/**
* Callback when a message generated during query execution is issued
*/
@@ -504,7 +508,8 @@ export interface MainThreadDataProtocolShape extends IDisposable {
$onQueryComplete(handle: number, result: sqlops.QueryExecuteCompleteNotificationResult): void;
$onBatchStart(handle: number, batchInfo: sqlops.QueryExecuteBatchNotificationParams): void;
$onBatchComplete(handle: number, batchInfo: sqlops.QueryExecuteBatchNotificationParams): void;
$onResultSetComplete(handle: number, resultSetInfo: sqlops.QueryExecuteResultSetCompleteNotificationParams): void;
$onResultSetAvailable(handle: number, resultSetInfo: sqlops.QueryExecuteResultSetNotificationParams): void;
$onResultSetUpdated(handle: number, resultSetInfo: sqlops.QueryExecuteResultSetNotificationParams): void;
$onQueryMessage(handle: number, message: sqlops.QueryExecuteMessageParams): void;
$onObjectExplorerSessionCreated(handle: number, message: sqlops.ObjectExplorerSession): void;
$onObjectExplorerSessionDisconnected(handle: number, message: sqlops.ObjectExplorerSession): void;

View File

@@ -349,7 +349,7 @@ suite('SQL QueryEditor Tests', () => {
queryActionInstantiationService.setup(x => x.createInstance(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()))
.returns((definition, editor, action, selectBox) => {
if (definition.ID === 'listDatabaseQueryActionItem') {
let item = new ListDatabasesActionItem(editor, action, queryConnectionService.object, undefined, undefined, undefined,configurationService.object);
let item = new ListDatabasesActionItem(editor, action, queryConnectionService.object, undefined, undefined, undefined, configurationService.object);
return item;
}
// Default

View File

@@ -830,7 +830,7 @@ declare namespace Slick {
* @param newData New databinding source using a regular JavaScript array..
* @param scrollToTop If true, the grid will reset the vertical scroll position to the top of the grid.
**/
public setData(newData: T[], scrollToTop: boolean): void;
public setData(newData: T[], scrollToTop?: boolean): void;
/**
* Sets a new source for databinding and removes all rendered rows. Note that this doesn't render the new rows - you can follow it with a call to render() to do that.

View File

@@ -6389,9 +6389,9 @@ slice-ansi@0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
"slickgrid@github:anthonydresser/SlickGrid#2.3.28":
version "2.3.28"
resolved "https://codeload.github.com/anthonydresser/SlickGrid/tar.gz/57db056e2bd15451e6ad30946a71df49e1c9451f"
"slickgrid@github:anthonydresser/SlickGrid#2.3.29":
version "2.3.29"
resolved "https://codeload.github.com/anthonydresser/SlickGrid/tar.gz/40b88f10d36d35f350838d1a2142c4b790701709"
dependencies:
jquery ">=1.8.0"
jquery-ui ">=1.8.0"