Merge branch 'master' into release/1.17
@@ -92,11 +92,6 @@ steps:
|
||||
node build/azure-pipelines/mixin
|
||||
displayName: Mix in quality
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
yarn gulp install-sqltoolsservice
|
||||
displayName: Install sqltoolsservice
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
yarn gulp package-rebuild-extensions
|
||||
|
||||
13
build/azure-pipelines/docker/createDrop.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
set -e
|
||||
REPO="$(pwd)"
|
||||
ROOT="$REPO/.."
|
||||
|
||||
PLATFORM_LINUX="linux-x64"
|
||||
SERVER_BUILD_NAME="azuredatastudio-server-$PLATFORM_LINUX"
|
||||
|
||||
# create docker
|
||||
mkdir -p $REPO/.build/docker
|
||||
docker build -t azuredatastudio-server -f $REPO/build/azure-pipelines/docker/Dockerfile $ROOT/$SERVER_BUILD_NAME
|
||||
docker save azuredatastudio-server | gzip > $REPO/.build/docker/azuredatastudio-server-docker.tar.gz
|
||||
|
||||
node build/azure-pipelines/common/copyArtifacts.js
|
||||
96
build/azure-pipelines/docker/sql-product-build-docker.yml
Normal file
@@ -0,0 +1,96 @@
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: '10.15.1'
|
||||
|
||||
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@3
|
||||
inputs:
|
||||
versionSpec: "1.x"
|
||||
|
||||
- task: AzureKeyVault@1
|
||||
displayName: 'Azure Key Vault: Get Secrets'
|
||||
inputs:
|
||||
azureSubscription: 'ClientToolsInfra_670062 (88d5392f-a34f-4769-b405-f597fc533613)'
|
||||
KeyVaultName: ado-secrets
|
||||
SecretsFilter: 'github-distro-mixin-password'
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
cat << EOF > ~/.netrc
|
||||
machine github.com
|
||||
login azuredatastudio
|
||||
password $(github-distro-mixin-password)
|
||||
EOF
|
||||
|
||||
git config user.email "andresse@microsoft.com"
|
||||
git config user.name "AzureDataStudio"
|
||||
displayName: Prepare tooling
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git"
|
||||
git fetch distro
|
||||
git merge $(node -p "require('./package.json').distro")
|
||||
displayName: Merge distro
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||
inputs:
|
||||
keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock, !samples/**/yarn.lock'
|
||||
targetfolder: '**/node_modules, !**/node_modules/**/node_modules, !samples/**/node_modules'
|
||||
vstsFeed: 'BuildCache'
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
CHILD_CONCURRENCY=1 yarn --frozen-lockfile
|
||||
displayName: Install dependencies
|
||||
env:
|
||||
GITHUB_TOKEN: $(github-distro-mixin-password)
|
||||
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1
|
||||
inputs:
|
||||
keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock, !samples/**/yarn.lock'
|
||||
targetfolder: '**/node_modules, !**/node_modules/**/node_modules, !samples/**/node_modules'
|
||||
vstsFeed: 'BuildCache'
|
||||
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
yarn postinstall
|
||||
displayName: Run postinstall scripts
|
||||
condition: and(succeeded(), eq(variables['CacheRestored'], 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
node build/azure-pipelines/mixin
|
||||
displayName: Mix in quality
|
||||
|
||||
- task: DownloadPipelineArtifact@2
|
||||
inputs:
|
||||
buildType: 'current'
|
||||
targetPath: '$(Build.SourcesDirectory)/.build'
|
||||
artifactName: drop
|
||||
itemPattern: |
|
||||
drop/linux/server/*.tar.gz
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
for f in $(Build.SourcesDirectory)/.build/linux/server/*.tar.gz
|
||||
do
|
||||
tar -C $(agent.builddirectory) -zxvf $f
|
||||
rm $f
|
||||
done
|
||||
displayName: Unzip artifacts
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
./build/azure-pipelines/docker/createDrop.sh
|
||||
displayName: Create Drop
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: drop'
|
||||
|
||||
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
||||
displayName: 'Component Detection'
|
||||
inputs:
|
||||
failOnAlert: true
|
||||
@@ -29,9 +29,4 @@ SERVER_TARBALL_PATH="$REPO/.build/linux/server/$SERVER_TARBALL_FILENAME"
|
||||
rm -rf $ROOT/azuredatastudio-server-*.tar.*
|
||||
(cd $ROOT && mv $LEGACY_SERVER_BUILD_NAME $SERVER_BUILD_NAME && tar --owner=0 --group=0 -czf $SERVER_TARBALL_PATH $SERVER_BUILD_NAME)
|
||||
|
||||
# create docker
|
||||
mkdir -p $REPO/.build/docker
|
||||
docker build -t azuredatastudio-server -f $REPO/build/azure-pipelines/docker/Dockerfile $ROOT/$SERVER_BUILD_NAME
|
||||
docker save azuredatastudio-server | gzip > $REPO/.build/docker/azuredatastudio-server-docker.tar.gz
|
||||
|
||||
node build/azure-pipelines/common/copyArtifacts.js
|
||||
|
||||
@@ -85,12 +85,6 @@ steps:
|
||||
node build/azure-pipelines/mixin
|
||||
displayName: Mix in quality
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
yarn gulp install-sqltoolsservice
|
||||
yarn gulp install-ssmsmin
|
||||
displayName: Install extension binaries
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
yarn gulp vscode-linux-x64-min-ci
|
||||
|
||||
@@ -37,6 +37,16 @@ jobs:
|
||||
- template: linux/sql-product-build-linux.yml
|
||||
timeoutInMinutes: 70
|
||||
|
||||
- job: Docker
|
||||
condition: eq(variables['VSCODE_BUILD_DOCKER'], 'true')
|
||||
pool:
|
||||
vmImage: 'Ubuntu-16.04'
|
||||
container: linux-x64
|
||||
dependsOn:
|
||||
- Linux
|
||||
steps:
|
||||
- template: docker/sql-product-build-docker.yml
|
||||
|
||||
- job: Windows
|
||||
condition: eq(variables['VSCODE_BUILD_WIN32'], 'true')
|
||||
pool:
|
||||
@@ -64,6 +74,7 @@ jobs:
|
||||
dependsOn:
|
||||
- macOS
|
||||
- Linux
|
||||
- Docker
|
||||
- Windows
|
||||
- Windows_Test
|
||||
steps:
|
||||
|
||||
@@ -90,12 +90,6 @@ steps:
|
||||
exec { node build/azure-pipelines/mixin }
|
||||
displayName: Mix in quality
|
||||
|
||||
- powershell: |
|
||||
. build/azure-pipelines/win32/exec.ps1
|
||||
$ErrorActionPreference = "Stop"
|
||||
exec { yarn gulp "install-sqltoolsservice" }
|
||||
displayName: Install sqltoolsservice
|
||||
|
||||
- powershell: |
|
||||
. build/azure-pipelines/win32/exec.ps1
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
@@ -97,7 +97,7 @@ const indentationFilter = [
|
||||
'!extensions/markdown-language-features/media/*.js',
|
||||
// {{SQL CARBON EDIT}}
|
||||
'!build/actions/**/dist/*',
|
||||
'!**/*.{xlf,docx,sql,vsix,bacpac,ipynb}',
|
||||
'!**/*.{xlf,docx,sql,vsix,bacpac,ipynb,jpg}',
|
||||
'!extensions/mssql/sqltoolsservice/**',
|
||||
'!extensions/import/flatfileimportservice/**',
|
||||
'!extensions/admin-tool-ext-win/ssmsmin/**',
|
||||
|
||||
@@ -5,20 +5,15 @@
|
||||
|
||||
'use strict';
|
||||
const gulp = require('gulp');
|
||||
const util = require('./lib/util');
|
||||
const tsfmt = require('typescript-formatter');
|
||||
const es = require('event-stream');
|
||||
const filter = require('gulp-filter');
|
||||
const serviceDownloader = require('service-downloader').ServiceDownloadProvider;
|
||||
const platform = require('service-downloader/out/platform').PlatformInformation;
|
||||
const path = require('path');
|
||||
const ext = require('./lib/extensions');
|
||||
const task = require('./lib/task');
|
||||
const glob = require('glob');
|
||||
const vsce = require('vsce');
|
||||
const mkdirp = require('mkdirp');
|
||||
const fs = require('fs').promises;
|
||||
const assert = require('assert');
|
||||
|
||||
gulp.task('fmt', () => formatStagedFiles());
|
||||
const formatFiles = (some) => {
|
||||
@@ -94,40 +89,6 @@ const formatStagedFiles = () => {
|
||||
});
|
||||
};
|
||||
|
||||
async function installService(configPath, runtimId) {
|
||||
const absoluteConfigPath = require.resolve(configPath);
|
||||
const config = require(absoluteConfigPath);
|
||||
const runtime = runtimId || (await platform.getCurrent()).runtimeId;
|
||||
// fix path since it won't be correct
|
||||
config.installDirectory = path.join(path.dirname(absoluteConfigPath), config.installDirectory);
|
||||
console.log('install diectory', config.installDirectory);
|
||||
let installer = new serviceDownloader(config);
|
||||
installer.eventEmitter.onAny((event, ...values) => {
|
||||
console.log(`ServiceDownloader Event : ${event}${values && values.length > 0 ? ` - ${values.join(' ')}` : ''}`);
|
||||
});
|
||||
let serviceInstallFolder = installer.getInstallDirectory(runtime);
|
||||
console.log('Cleaning up the install folder: ' + serviceInstallFolder);
|
||||
try {
|
||||
await util.rimraf(serviceInstallFolder)();
|
||||
} catch (e) {
|
||||
console.error('failed to delete the install folder error: ' + e);
|
||||
throw e;
|
||||
}
|
||||
await installer.installService(runtime);
|
||||
let stat;
|
||||
for (const file of config.executableFiles) {
|
||||
try {
|
||||
stat = await fs.stat(path.join(serviceInstallFolder, file));
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
assert(stat);
|
||||
}
|
||||
|
||||
gulp.task('install-sqltoolsservice', () => installService('../extensions/mssql/config.json'));
|
||||
|
||||
gulp.task('install-ssmsmin', () => installService('../extensions/admin-tool-ext-win/config.json', 'Windows_64')); // admin-tool-ext is a windows only extension, and we only ship a 64 bit version, so locking the binaries as such
|
||||
|
||||
const root = path.dirname(__dirname);
|
||||
|
||||
gulp.task('package-external-extensions', task.series(
|
||||
|
||||
@@ -47,7 +47,6 @@
|
||||
"rollup": "^1.20.3",
|
||||
"rollup-plugin-commonjs": "^10.1.0",
|
||||
"rollup-plugin-node-resolve": "^5.2.0",
|
||||
"service-downloader": "0.2.1",
|
||||
"terser": "4.3.8",
|
||||
"typescript": "^3.9.0-dev.20200327",
|
||||
"vsce": "1.48.0",
|
||||
|
||||
147
build/yarn.lock
@@ -420,20 +420,6 @@ acorn@^7.0.0:
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c"
|
||||
integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==
|
||||
|
||||
agent-base@4:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9"
|
||||
integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==
|
||||
dependencies:
|
||||
es6-promisify "^5.0.0"
|
||||
|
||||
agent-base@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
|
||||
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
|
||||
dependencies:
|
||||
es6-promisify "^5.0.0"
|
||||
|
||||
ajv@^4.9.1:
|
||||
version "4.11.8"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
|
||||
@@ -596,13 +582,6 @@ async-each@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.2.tgz#8b8a7ca2a658f927e9f307d6d1a42f4199f0f735"
|
||||
integrity sha512-6xrbvN0MOBKSJDdonmSSz2OwFSgxRaVtBDes26mj9KIGtDo+g9xosFRSC+i1gQh2oAN/tQ62AI/pGZGQjVOiRg==
|
||||
|
||||
async-retry@^1.2.3:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.2.3.tgz#a6521f338358d322b1a0012b79030c6f411d1ce0"
|
||||
integrity sha512-tfDb02Th6CE6pJUF2gjW5ZVjsgwlucVXOEQMvEX9JgSJMs9gAX+Nz3xRuJBKuUYjTSYORqvDBORdAQ3LU59g7Q==
|
||||
dependencies:
|
||||
retry "0.12.0"
|
||||
|
||||
asynckit@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
@@ -834,11 +813,6 @@ chownr@^1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494"
|
||||
integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==
|
||||
|
||||
chownr@^1.1.3:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
|
||||
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
|
||||
|
||||
class-utils@^0.3.5:
|
||||
version "0.3.6"
|
||||
resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463"
|
||||
@@ -1036,20 +1010,6 @@ debug@2.X, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3:
|
||||
dependencies:
|
||||
ms "2.0.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"
|
||||
|
||||
debug@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
|
||||
@@ -1215,18 +1175,6 @@ entities@^1.1.1, entities@~1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
|
||||
integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
|
||||
|
||||
es6-promise@^4.0.3:
|
||||
version "4.2.6"
|
||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.6.tgz#b685edd8258886365ea62b57d30de28fadcd974f"
|
||||
integrity sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==
|
||||
|
||||
es6-promisify@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
|
||||
integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
|
||||
dependencies:
|
||||
es6-promise "^4.0.3"
|
||||
|
||||
escape-string-regexp@^1.0.2:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
@@ -1262,11 +1210,6 @@ estree-walker@^0.6.1:
|
||||
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362"
|
||||
integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==
|
||||
|
||||
eventemitter2@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-5.0.1.tgz#6197a095d5fb6b57e8942f6fd7eaad63a09c9452"
|
||||
integrity sha1-YZegldX7a1folC9v1+qtY6CclFI=
|
||||
|
||||
execa@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
|
||||
@@ -1457,13 +1400,6 @@ fs-minipass@^1.2.5:
|
||||
dependencies:
|
||||
minipass "^2.2.1"
|
||||
|
||||
fs-minipass@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
|
||||
integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
|
||||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
@@ -1805,14 +1741,6 @@ htmlparser2@^3.9.1:
|
||||
inherits "^2.0.1"
|
||||
readable-stream "^3.0.6"
|
||||
|
||||
http-proxy-agent@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
|
||||
integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
|
||||
dependencies:
|
||||
agent-base "4"
|
||||
debug "3.1.0"
|
||||
|
||||
http-signature@~1.1.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
|
||||
@@ -1831,14 +1759,6 @@ http-signature@~1.2.0:
|
||||
jsprim "^1.2.2"
|
||||
sshpk "^1.7.0"
|
||||
|
||||
https-proxy-agent@^2.2.3:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
|
||||
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
|
||||
dependencies:
|
||||
agent-base "^4.3.0"
|
||||
debug "^3.1.0"
|
||||
|
||||
iconv-lite@0.4.23:
|
||||
version "0.4.23"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
|
||||
@@ -2468,13 +2388,6 @@ minipass@^2.2.1, minipass@^2.3.4:
|
||||
safe-buffer "^5.1.2"
|
||||
yallist "^3.0.0"
|
||||
|
||||
minipass@^3.0.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.1.tgz#7607ce778472a185ad6d89082aa2070f79cedcd5"
|
||||
integrity sha512-UFqVihv6PQgwj8/yTGvl9kPz7xIAY+R5z6XYjRInD3Gk3qx6QGSD6zEcpeG4Dy/lQnv1J6zv8ejV90hyYIKf3w==
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
minizlib@^1.1.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614"
|
||||
@@ -2482,14 +2395,6 @@ minizlib@^1.1.1:
|
||||
dependencies:
|
||||
minipass "^2.2.1"
|
||||
|
||||
minizlib@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.0.tgz#fd52c645301ef09a63a2c209697c294c6ce02cf3"
|
||||
integrity sha512-EzTZN/fjSvifSX0SlqUERCN39o6T40AMarPbv0MrarSFtIITCBh7bi+dU8nxGFHuqs9jdIAeoYoKuQAAASsPPA==
|
||||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
yallist "^4.0.0"
|
||||
|
||||
mixin-deep@^1.2.0:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe"
|
||||
@@ -2505,11 +2410,6 @@ mkdirp@^0.5.0, mkdirp@^0.5.1:
|
||||
dependencies:
|
||||
minimist "0.0.8"
|
||||
|
||||
mkdirp@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.3.tgz#4cf2e30ad45959dddea53ad97d518b6c8205e1ea"
|
||||
integrity sha512-6uCP4Qc0sWsgMLy1EOqqS/3rjDHOEnsStVr/4vtAIK2Y5i2kA7lFFejYrpIyiN9w0pYf4ckeCYT9f1r1P9KX5g==
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
@@ -2738,7 +2638,7 @@ os-name@^3.1.0:
|
||||
macos-release "^2.2.0"
|
||||
windows-release "^3.1.0"
|
||||
|
||||
os-tmpdir@^1.0.0, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2:
|
||||
os-tmpdir@^1.0.0, os-tmpdir@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
|
||||
@@ -3047,11 +2947,6 @@ ret@~0.1.10:
|
||||
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
|
||||
integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
|
||||
|
||||
retry@0.12.0:
|
||||
version "0.12.0"
|
||||
resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b"
|
||||
integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=
|
||||
|
||||
reusify@^1.0.0:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
||||
@@ -3169,20 +3064,6 @@ semver@^6.3.0:
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||
|
||||
service-downloader@0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/service-downloader/-/service-downloader-0.2.1.tgz#8bd756bc4bc0cbfdf04fe71d4337f19ce6196203"
|
||||
integrity sha512-5IEy2nyMJj/f41pI65b8RMeJyCecGNrMmNCpUW8hckZ9cBMyX+VCp8GjYoM6Mz/X0XSaGVz7V5gtCWjfeJI7gA==
|
||||
dependencies:
|
||||
async-retry "^1.2.3"
|
||||
eventemitter2 "^5.0.1"
|
||||
http-proxy-agent "^2.1.0"
|
||||
https-proxy-agent "^2.2.3"
|
||||
mkdirp "^0.5.1"
|
||||
tar "^6.0.1"
|
||||
tmp "^0.0.33"
|
||||
yauzl "^2.10.0"
|
||||
|
||||
set-blocking@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
||||
@@ -3436,18 +3317,6 @@ tar@^4:
|
||||
safe-buffer "^5.1.2"
|
||||
yallist "^3.0.2"
|
||||
|
||||
tar@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.1.tgz#7b3bd6c313cb6e0153770108f8d70ac298607efa"
|
||||
integrity sha512-bKhKrrz2FJJj5s7wynxy/fyxpE0CmCjmOQ1KV4KkgXFWOgoIT/NbTMnB1n+LFNrNk0SSBVGGxcK5AGsyC+pW5Q==
|
||||
dependencies:
|
||||
chownr "^1.1.3"
|
||||
fs-minipass "^2.0.0"
|
||||
minipass "^3.0.0"
|
||||
minizlib "^2.1.0"
|
||||
mkdirp "^1.0.3"
|
||||
yallist "^4.0.0"
|
||||
|
||||
terser@*:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-4.2.1.tgz#1052cfe17576c66e7bc70fcc7119f22b155bdac1"
|
||||
@@ -3486,13 +3355,6 @@ tmp@0.0.29:
|
||||
dependencies:
|
||||
os-tmpdir "~1.0.1"
|
||||
|
||||
tmp@^0.0.33:
|
||||
version "0.0.33"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
|
||||
integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
|
||||
dependencies:
|
||||
os-tmpdir "~1.0.2"
|
||||
|
||||
to-object-path@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"
|
||||
@@ -3853,12 +3715,7 @@ yallist@^3.0.0, yallist@^3.0.2:
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9"
|
||||
integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==
|
||||
|
||||
yallist@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||
|
||||
yauzl@^2.10.0, yauzl@^2.3.1:
|
||||
yauzl@^2.3.1:
|
||||
version "2.10.0"
|
||||
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
|
||||
integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=
|
||||
|
||||
1
docs/UX-Design-Guidelines.md
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
BIN
docs/overview_screen.jpg
Normal file
|
After Width: | Height: | Size: 60 KiB |
@@ -4,6 +4,5 @@ src
|
||||
.gitignore
|
||||
coverConfig.json
|
||||
tsconfig.json
|
||||
InstallSsmsMin.bat
|
||||
cgmanifest.json
|
||||
.vscode
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
@echo off
|
||||
|
||||
REM Run this command to install SsmsMin for local development testing
|
||||
gulp install-ssmsmin
|
||||
43
extensions/admin-tool-ext-win/build/postinstall.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
(async () => {
|
||||
const serviceDownloader = require('service-downloader').ServiceDownloadProvider;
|
||||
const path = require('path');
|
||||
const fs = require('fs').promises;
|
||||
const rimraf = require('rimraf');
|
||||
const assert = require('assert');
|
||||
const readline = require('readline');
|
||||
|
||||
async function installService(configPath) {
|
||||
const absoluteConfigPath = require.resolve('../config.json');
|
||||
const config = require(absoluteConfigPath);
|
||||
const runtime = 'Windows_64';
|
||||
// fix path since it won't be correct
|
||||
config.installDirectory = path.join(path.dirname(absoluteConfigPath), config.installDirectory);
|
||||
let installer = new serviceDownloader(config);
|
||||
installer.eventEmitter.onAny((event, ...values) => {
|
||||
readline.cursorTo(process.stdout, 0);
|
||||
readline.clearLine(process.stdout, 0);
|
||||
process.stdout.write(`${event}${values && values.length > 0 ? ` - ${values.join(' ')}` : ''}`);
|
||||
});
|
||||
let serviceInstallFolder = installer.getInstallDirectory(runtime);
|
||||
await new Promise((rs, rj) => rimraf(serviceInstallFolder, (e) => e ? rj(e) : rs()));
|
||||
await installer.installService(runtime);
|
||||
let stat;
|
||||
for (const file of config.executableFiles) {
|
||||
try {
|
||||
stat = await fs.stat(path.join(serviceInstallFolder, file));
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
assert(stat);
|
||||
}
|
||||
|
||||
await installService();
|
||||
})().catch(e => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -12,6 +12,9 @@
|
||||
"vscode": "^1.30.1",
|
||||
"azdata": ">=1.8.0"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "node ./build/postinstall.js"
|
||||
},
|
||||
"activationEvents": [
|
||||
"onCommand:adminToolExtWin.launchSsmsMinPropertiesDialog",
|
||||
"onCommand:adminToolExtWin.launchSsmsMinGswDialog"
|
||||
@@ -72,6 +75,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"ads-extension-telemetry": "github:Charles-Gagnon/ads-extension-telemetry#0.1.0",
|
||||
"service-downloader": "0.2.1",
|
||||
"vscode-nls": "^3.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -28,6 +28,13 @@ abbrev@1.0.x:
|
||||
dependencies:
|
||||
vscode-extension-telemetry "0.1.1"
|
||||
|
||||
agent-base@4, agent-base@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
|
||||
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
|
||||
dependencies:
|
||||
es6-promisify "^5.0.0"
|
||||
|
||||
amdefine@>=0.0.4, amdefine@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
|
||||
@@ -96,6 +103,13 @@ array-slice@^0.2.3:
|
||||
resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5"
|
||||
integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU=
|
||||
|
||||
async-retry@^1.2.3:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.1.tgz#139f31f8ddce50c0870b0ba558a6079684aaed55"
|
||||
integrity sha512-aiieFW/7h3hY0Bq5d+ktDBejxuwR78vRu9hDUdR8rNhSaQ29VzPL4AoIRG7D/c7tdenwOcKvgPM6tIxB3cB6HA==
|
||||
dependencies:
|
||||
retry "0.12.0"
|
||||
|
||||
async@1.x:
|
||||
version "1.5.2"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
|
||||
@@ -119,6 +133,11 @@ browser-stdout@1.3.1:
|
||||
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
|
||||
integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
|
||||
|
||||
buffer-crc32@~0.2.3:
|
||||
version "0.2.13"
|
||||
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
|
||||
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
|
||||
|
||||
buffer-from@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||
@@ -134,6 +153,11 @@ charenc@~0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
|
||||
integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
|
||||
|
||||
chownr@^1.1.3:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
|
||||
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
|
||||
|
||||
commander@2.15.1:
|
||||
version "2.15.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
|
||||
@@ -209,6 +233,18 @@ diff@3.5.0:
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
|
||||
integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
|
||||
|
||||
es6-promise@^4.0.3:
|
||||
version "4.2.8"
|
||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
|
||||
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
|
||||
|
||||
es6-promisify@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
|
||||
integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
|
||||
dependencies:
|
||||
es6-promise "^4.0.3"
|
||||
|
||||
escape-string-regexp@1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||
@@ -241,6 +277,11 @@ esutils@^2.0.2:
|
||||
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
||||
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
|
||||
|
||||
eventemitter2@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-5.0.1.tgz#6197a095d5fb6b57e8942f6fd7eaad63a09c9452"
|
||||
integrity sha1-YZegldX7a1folC9v1+qtY6CclFI=
|
||||
|
||||
extend-shallow@^1.1.2:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071"
|
||||
@@ -253,6 +294,20 @@ fast-levenshtein@~2.0.6:
|
||||
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
|
||||
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
|
||||
|
||||
fd-slicer@~1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
|
||||
integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=
|
||||
dependencies:
|
||||
pend "~1.2.0"
|
||||
|
||||
fs-minipass@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
|
||||
integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
|
||||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
@@ -324,6 +379,22 @@ he@1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
|
||||
integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0=
|
||||
|
||||
http-proxy-agent@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
|
||||
integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
|
||||
dependencies:
|
||||
agent-base "4"
|
||||
debug "3.1.0"
|
||||
|
||||
https-proxy-agent@^2.2.3:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
|
||||
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
|
||||
dependencies:
|
||||
agent-base "^4.3.0"
|
||||
debug "^3.1.0"
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
@@ -419,11 +490,31 @@ minimist@0.0.8:
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
|
||||
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
|
||||
|
||||
minimist@^1.2.5:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
||||
|
||||
minimist@~0.0.1:
|
||||
version "0.0.10"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
|
||||
integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=
|
||||
|
||||
minipass@^3.0.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.1.tgz#7607ce778472a185ad6d89082aa2070f79cedcd5"
|
||||
integrity sha512-UFqVihv6PQgwj8/yTGvl9kPz7xIAY+R5z6XYjRInD3Gk3qx6QGSD6zEcpeG4Dy/lQnv1J6zv8ejV90hyYIKf3w==
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
minizlib@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.0.tgz#fd52c645301ef09a63a2c209697c294c6ce02cf3"
|
||||
integrity sha512-EzTZN/fjSvifSX0SlqUERCN39o6T40AMarPbv0MrarSFtIITCBh7bi+dU8nxGFHuqs9jdIAeoYoKuQAAASsPPA==
|
||||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
yallist "^4.0.0"
|
||||
|
||||
mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@~0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
|
||||
@@ -431,6 +522,18 @@ mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@~0.5.1:
|
||||
dependencies:
|
||||
minimist "0.0.8"
|
||||
|
||||
mkdirp@^0.5.1:
|
||||
version "0.5.4"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.4.tgz#fd01504a6797ec5c9be81ff43d204961ed64a512"
|
||||
integrity sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==
|
||||
dependencies:
|
||||
minimist "^1.2.5"
|
||||
|
||||
mkdirp@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.3.tgz#4cf2e30ad45959dddea53ad97d518b6c8205e1ea"
|
||||
integrity sha512-6uCP4Qc0sWsgMLy1EOqqS/3rjDHOEnsStVr/4vtAIK2Y5i2kA7lFFejYrpIyiN9w0pYf4ckeCYT9f1r1P9KX5g==
|
||||
|
||||
mocha-junit-reporter@^1.17.0:
|
||||
version "1.23.1"
|
||||
resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-1.23.1.tgz#ba11519c0b967f404e4123dd69bc4ba022ab0f12"
|
||||
@@ -516,11 +619,21 @@ optionator@^0.8.1:
|
||||
type-check "~0.3.2"
|
||||
word-wrap "~1.2.3"
|
||||
|
||||
os-tmpdir@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
|
||||
|
||||
path-is-absolute@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
|
||||
|
||||
pend@~1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
|
||||
integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA=
|
||||
|
||||
plugin-error@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace"
|
||||
@@ -571,11 +684,30 @@ resolve@1.1.x:
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
|
||||
integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
|
||||
|
||||
retry@0.12.0:
|
||||
version "0.12.0"
|
||||
resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b"
|
||||
integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=
|
||||
|
||||
semver@^5.3.0:
|
||||
version "5.6.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
|
||||
integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
|
||||
|
||||
service-downloader@0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/service-downloader/-/service-downloader-0.2.1.tgz#8bd756bc4bc0cbfdf04fe71d4337f19ce6196203"
|
||||
integrity sha512-5IEy2nyMJj/f41pI65b8RMeJyCecGNrMmNCpUW8hckZ9cBMyX+VCp8GjYoM6Mz/X0XSaGVz7V5gtCWjfeJI7gA==
|
||||
dependencies:
|
||||
async-retry "^1.2.3"
|
||||
eventemitter2 "^5.0.1"
|
||||
http-proxy-agent "^2.1.0"
|
||||
https-proxy-agent "^2.2.3"
|
||||
mkdirp "^0.5.1"
|
||||
tar "^6.0.1"
|
||||
tmp "^0.0.33"
|
||||
yauzl "^2.10.0"
|
||||
|
||||
should-equal@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/should-equal/-/should-equal-2.0.0.tgz#6072cf83047360867e68e98b09d71143d04ee0c3"
|
||||
@@ -671,6 +803,18 @@ supports-color@^3.1.0:
|
||||
dependencies:
|
||||
has-flag "^1.0.0"
|
||||
|
||||
tar@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.1.tgz#7b3bd6c313cb6e0153770108f8d70ac298607efa"
|
||||
integrity sha512-bKhKrrz2FJJj5s7wynxy/fyxpE0CmCjmOQ1KV4KkgXFWOgoIT/NbTMnB1n+LFNrNk0SSBVGGxcK5AGsyC+pW5Q==
|
||||
dependencies:
|
||||
chownr "^1.1.3"
|
||||
fs-minipass "^2.0.0"
|
||||
minipass "^3.0.0"
|
||||
minizlib "^2.1.0"
|
||||
mkdirp "^1.0.3"
|
||||
yallist "^4.0.0"
|
||||
|
||||
through2@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.1.tgz#384e75314d49f32de12eebb8136b8eb6b5d59da9"
|
||||
@@ -679,6 +823,13 @@ through2@2.0.1:
|
||||
readable-stream "~2.0.0"
|
||||
xtend "~4.0.0"
|
||||
|
||||
tmp@^0.0.33:
|
||||
version "0.0.33"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
|
||||
integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
|
||||
dependencies:
|
||||
os-tmpdir "~1.0.2"
|
||||
|
||||
type-check@~0.3.2:
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
|
||||
@@ -759,6 +910,19 @@ xtend@~4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
|
||||
|
||||
yallist@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||
|
||||
yauzl@^2.10.0:
|
||||
version "2.10.0"
|
||||
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
|
||||
integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=
|
||||
dependencies:
|
||||
buffer-crc32 "~0.2.3"
|
||||
fd-slicer "~1.1.0"
|
||||
|
||||
zone.js@0.7.6:
|
||||
version "0.7.6"
|
||||
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009"
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
"description": "Manage and troubleshoot SQL Agent jobs",
|
||||
"provider": "MSSQL",
|
||||
"title": "SQL Agent",
|
||||
"group": "administration",
|
||||
"when": "connectionProvider == 'MSSQL' && !mssql:iscloud && mssql:engineedition != 11 && dashboardContext == 'server'",
|
||||
"container": {
|
||||
"controlhost-container": {
|
||||
@@ -91,7 +92,7 @@
|
||||
"vscodetestcover": "github:corivera/vscodetestcover#1.0.5"
|
||||
},
|
||||
"resolutions": {
|
||||
"esprima": "^4.0.0"
|
||||
"esprima": "^4.0.0"
|
||||
},
|
||||
"__metadata": {
|
||||
"id": "10",
|
||||
|
||||
@@ -219,12 +219,14 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
console.log('Base token was empty, account is stale.');
|
||||
return undefined;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.refreshAccessToken(account.key, baseToken.refreshToken, tenant, resource);
|
||||
} catch (ex) {
|
||||
console.log(ex);
|
||||
account.isStale = true;
|
||||
return undefined;
|
||||
console.log(`Could not refresh access token for ${JSON.stringify(tenant)} - silently removing the tenant from the user's account.`);
|
||||
azureAccount.properties.tenants = azureAccount.properties.tenants.filter(t => t.id !== tenant.id);
|
||||
console.log(ex, ex?.data, ex?.response);
|
||||
continue;
|
||||
}
|
||||
|
||||
cachedTokens = await this.getCachedToken(account.key, resource.id, tenant.id);
|
||||
@@ -243,9 +245,12 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
|
||||
if (azureAccount.properties.subscriptions) {
|
||||
azureAccount.properties.subscriptions.forEach(subscription => {
|
||||
response[subscription.id] = {
|
||||
...response[subscription.tenantId]
|
||||
};
|
||||
// Make sure that tenant has information populated.
|
||||
if (response[subscription.tenantId]) {
|
||||
response[subscription.id] = {
|
||||
...response[subscription.tenantId]
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -5,13 +5,42 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import axios, { AxiosRequestConfig } from 'axios';
|
||||
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
|
||||
import * as WS from 'ws';
|
||||
|
||||
import { IAzureTerminalService } from '../interfaces';
|
||||
import { AzureAccount, AzureAccountSecurityToken, Tenant } from '../../account-provider/interfaces';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
|
||||
const handleNeverUsed = async (): Promise<void> => {
|
||||
const neverUsedString = localize('azure.coudTerminal.neverUsed', "If you have not launched Azure Cloud Shell from this account before, please visit https://shell.azure.com/ to get started. Once you are set up, you can use AzureCloud Shell directly in Azure Data Studio.");
|
||||
enum TerminalOption {
|
||||
OPEN_SITE,
|
||||
OK
|
||||
}
|
||||
interface TerminalMessageItem extends vscode.MessageItem {
|
||||
action: TerminalOption;
|
||||
}
|
||||
|
||||
const openAzureShellButton: TerminalMessageItem = {
|
||||
action: TerminalOption.OPEN_SITE,
|
||||
title: localize('azure.cloudTerminal.openAzureShell', "Open Azure Shell")
|
||||
};
|
||||
|
||||
const okButton: TerminalMessageItem = {
|
||||
action: TerminalOption.OK,
|
||||
title: localize('azure.cloudTerminal.ok', "OK")
|
||||
};
|
||||
|
||||
const option = await vscode.window.showInformationMessage<TerminalMessageItem>(neverUsedString, openAzureShellButton, okButton);
|
||||
|
||||
if (option.action === TerminalOption.OPEN_SITE) {
|
||||
vscode.env.openExternal(vscode.Uri.parse('https://aka.ms/AA83f8f'));
|
||||
}
|
||||
};
|
||||
|
||||
export class AzureTerminalService implements IAzureTerminalService {
|
||||
private readonly apiVersion = '?api-version=2018-10-01';
|
||||
|
||||
@@ -31,9 +60,16 @@ export class AzureTerminalService implements IAzureTerminalService {
|
||||
};
|
||||
|
||||
const metadata = account.properties.providerSettings;
|
||||
|
||||
const userSettingsUri = this.getConsoleUserSettingsUri(metadata.settings.armResource.endpoint);
|
||||
const userSettingsResult = await axios.get(userSettingsUri, settings);
|
||||
|
||||
let userSettingsResult: AxiosResponse<any>;
|
||||
try {
|
||||
userSettingsResult = await axios.get(userSettingsUri, settings);
|
||||
} catch (ex) {
|
||||
console.log(ex, ex.response);
|
||||
await handleNeverUsed();
|
||||
return;
|
||||
}
|
||||
|
||||
const preferredShell = userSettingsResult.data?.properties?.preferredShellType ?? 'bash';
|
||||
const preferredLocation = userSettingsResult.data?.properties?.preferredLocation;
|
||||
@@ -43,7 +79,14 @@ export class AzureTerminalService implements IAzureTerminalService {
|
||||
settings.headers['x-ms-console-preferred-location'] = preferredLocation;
|
||||
}
|
||||
|
||||
const provisionResult = await axios.put(consoleRequestUri, {}, settings);
|
||||
let provisionResult: AxiosResponse<any>;
|
||||
try {
|
||||
provisionResult = await axios.put(consoleRequestUri, {}, settings);
|
||||
} catch (ex) {
|
||||
console.log(ex, ex.response);
|
||||
await handleNeverUsed();
|
||||
return;
|
||||
}
|
||||
|
||||
if (provisionResult.data?.properties?.provisioningState !== 'Succeeded') {
|
||||
throw new Error(provisionResult.data);
|
||||
@@ -114,7 +157,7 @@ class AzureTerminal implements vscode.Pseudoterminal {
|
||||
}
|
||||
|
||||
async open(initialDimensions: vscode.TerminalDimensions): Promise<void> {
|
||||
return this.resetTerminalSize(initialDimensions);
|
||||
this.setDimensions(initialDimensions);
|
||||
}
|
||||
|
||||
close(): void {
|
||||
@@ -131,24 +174,22 @@ class AzureTerminal implements vscode.Pseudoterminal {
|
||||
}
|
||||
|
||||
async setDimensions(dimensions: vscode.TerminalDimensions): Promise<void> {
|
||||
return this.resetTerminalSize(dimensions);
|
||||
if (!dimensions) {
|
||||
return;
|
||||
}
|
||||
this.terminalDimensions = dimensions;
|
||||
return this.resetTerminalSize();
|
||||
}
|
||||
|
||||
private async resetTerminalSize(dimensions: vscode.TerminalDimensions): Promise<void> {
|
||||
private async resetTerminalSize(): Promise<void> {
|
||||
try {
|
||||
|
||||
if (!this.terminalDimensions) { // first time
|
||||
this.writeEmitter.fire(localize('azure.connectingShellTerminal', "Connecting terminal...\n"));
|
||||
}
|
||||
|
||||
if (dimensions) {
|
||||
this.terminalDimensions = dimensions;
|
||||
}
|
||||
|
||||
// Close the shell before this and restablish a new connection
|
||||
this.close();
|
||||
|
||||
const terminalUri = await this.establishTerminal(this.terminalDimensions);
|
||||
if (!terminalUri) {
|
||||
return;
|
||||
}
|
||||
this.socket = new WS(terminalUri);
|
||||
|
||||
this.socket.on('message', (data: WS.Data) => {
|
||||
@@ -172,13 +213,20 @@ class AzureTerminal implements vscode.Pseudoterminal {
|
||||
|
||||
|
||||
private async establishTerminal(dimensions: vscode.TerminalDimensions): Promise<string> {
|
||||
const terminalResult = await axios.post(`${this.consoleUri}/terminals?rows=${dimensions.rows}&cols=${dimensions.columns}&shell=${this.shell}`, undefined, {
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${this.token}`
|
||||
}
|
||||
});
|
||||
let terminalResult: AxiosResponse<any>;
|
||||
try {
|
||||
terminalResult = await axios.post(`${this.consoleUri}/terminals?rows=${dimensions.rows}&cols=${dimensions.columns}&shell=${this.shell}`, undefined, {
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${this.token}`
|
||||
}
|
||||
});
|
||||
} catch (ex) {
|
||||
console.log(ex, ex.response);
|
||||
await handleNeverUsed();
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const terminalUri = terminalResult.data?.socketUri;
|
||||
|
||||
|
||||
44
extensions/mssql/build/postinstall.js
Normal file
@@ -0,0 +1,44 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
(async () => {
|
||||
const serviceDownloader = require('service-downloader').ServiceDownloadProvider;
|
||||
const platform = require('service-downloader/out/platform').PlatformInformation;
|
||||
const path = require('path');
|
||||
const fs = require('fs').promises;
|
||||
const rimraf = require('rimraf');
|
||||
const assert = require('assert');
|
||||
const readline = require('readline');
|
||||
|
||||
async function installService() {
|
||||
const absoluteConfigPath = require.resolve('../config.json');
|
||||
const config = require(absoluteConfigPath);
|
||||
const runtime = (await platform.getCurrent()).runtimeId;
|
||||
// fix path since it won't be correct
|
||||
config.installDirectory = path.join(path.dirname(absoluteConfigPath), config.installDirectory);
|
||||
let installer = new serviceDownloader(config);
|
||||
installer.eventEmitter.onAny((event, ...values) => {
|
||||
readline.cursorTo(process.stdout, 0);
|
||||
readline.clearLine(process.stdout, 0);
|
||||
process.stdout.write(`${event}${values && values.length > 0 ? ` - ${values.join(' ')}` : ''}`);
|
||||
});
|
||||
let serviceInstallFolder = installer.getInstallDirectory(runtime);
|
||||
await new Promise((rs, rj) => rimraf(serviceInstallFolder, (e) => e ? rj(e) : rs()));
|
||||
await installer.installService(runtime);
|
||||
let stat;
|
||||
for (const file of config.executableFiles) {
|
||||
try {
|
||||
stat = await fs.stat(path.join(serviceInstallFolder, file));
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
assert(stat);
|
||||
}
|
||||
|
||||
await installService();
|
||||
})().catch(e => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
||||
"version": "2.0.0-release.53",
|
||||
"version": "2.0.0-release.56",
|
||||
"downloadFileNames": {
|
||||
"Windows_86": "win-x86-netcoreapp2.2.zip",
|
||||
"Windows_64": "win-x64-netcoreapp2.2.zip",
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
],
|
||||
"scripts": {
|
||||
"compile": "gulp compile-extension:mssql-client",
|
||||
"update-grammar": "node ../../build/npm/update-grammar.js Microsoft/vscode-mssql syntaxes/SQL.plist ./syntaxes/sql.tmLanguage.json"
|
||||
"update-grammar": "node ../../build/npm/update-grammar.js Microsoft/vscode-mssql syntaxes/SQL.plist ./syntaxes/sql.tmLanguage.json",
|
||||
"postinstall": "node ./build/postinstall.js"
|
||||
},
|
||||
"contributes": {
|
||||
"commands": [
|
||||
@@ -443,6 +444,7 @@
|
||||
"description": "%tab.bigDataClusterDescription%",
|
||||
"provider": "MSSQL",
|
||||
"title": "%title.bigDataCluster%",
|
||||
"group": "monitoring",
|
||||
"when": "connectionProvider == 'MSSQL' && mssql:iscluster && dashboardContext == 'server'",
|
||||
"container": {
|
||||
"grid-container": [
|
||||
@@ -493,10 +495,7 @@
|
||||
"title": "%mssql.tabs.databases%",
|
||||
"when": "dashboardContext == 'server'",
|
||||
"group": "home",
|
||||
"icon": {
|
||||
"light": "resources/light/database.svg",
|
||||
"dark": "resources/dark/database_inverse.svg"
|
||||
},
|
||||
"icon": "resources/database.svg",
|
||||
"container": {
|
||||
"widgets-container": [
|
||||
{
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#fff;}.cls-2{fill:none;}</style></defs><title>bv</title><path class="cls-1" d="M7.5,1q.563,0,1.246.062a10.962,10.962,0,0,1,1.367.215,7.406,7.406,0,0,1,1.3.418,3.558,3.558,0,0,1,1.039.664,1.991,1.991,0,0,1,.4.516A1.327,1.327,0,0,1,13,3.5v9a1.292,1.292,0,0,1-.152.629,2.2,2.2,0,0,1-.4.512,3.24,3.24,0,0,1-1.027.66,7.741,7.741,0,0,1-1.313.418,10.706,10.706,0,0,1-1.379.219Q8.047,15,7.5,15q-.562,0-1.246-.062a10.962,10.962,0,0,1-1.367-.215,7.323,7.323,0,0,1-1.3-.418,3.538,3.538,0,0,1-1.039-.664,1.958,1.958,0,0,1-.395-.516A1.322,1.322,0,0,1,2,12.5v-9a1.3,1.3,0,0,1,.152-.629,2.217,2.217,0,0,1,.4-.512A3.257,3.257,0,0,1,3.574,1.7a7.924,7.924,0,0,1,1.313-.418,10.883,10.883,0,0,1,1.379-.219Q6.953,1,7.5,1Zm0,1c-.266,0-.543.01-.832.027s-.579.05-.871.094-.577.1-.856.172a6.4,6.4,0,0,0-.793.254c-.078.031-.182.08-.312.144a3.808,3.808,0,0,0-.383.223,1.645,1.645,0,0,0-.32.277A.47.47,0,0,0,3,3.5a.3.3,0,0,0,.023.117.618.618,0,0,0,.063.11,1.445,1.445,0,0,0,.473.437,3.925,3.925,0,0,0,.695.328,6.414,6.414,0,0,0,.824.238q.438.1.871.157t.836.086Q7.189,5,7.5,5t.715-.027q.4-.027.836-.086t.871-.157a6.414,6.414,0,0,0,.824-.238,3.827,3.827,0,0,0,.692-.328,1.542,1.542,0,0,0,.476-.437.618.618,0,0,0,.063-.11A.3.3,0,0,0,12,3.5a.47.47,0,0,0-.133-.309,1.645,1.645,0,0,0-.32-.277,3.808,3.808,0,0,0-.383-.223c-.13-.064-.234-.113-.312-.144a6.4,6.4,0,0,0-.793-.254q-.418-.105-.856-.172t-.871-.094C8.043,2.01,7.766,2,7.5,2Zm0,12q.4,0,.832-.027t.871-.094q.438-.066.856-.168a5.182,5.182,0,0,0,.793-.258q.117-.046.312-.144a3.461,3.461,0,0,0,.383-.223,1.612,1.612,0,0,0,.32-.277A.47.47,0,0,0,12,12.5V4.984a4.572,4.572,0,0,1-1.008.485,8.312,8.312,0,0,1-1.168.312,11.149,11.149,0,0,1-1.207.168Q8.015,6,7.5,6T6.379,5.949a11.047,11.047,0,0,1-1.207-.168,8.368,8.368,0,0,1-1.164-.312A4.572,4.572,0,0,1,3,4.984V12.5a.47.47,0,0,0,.133.309,1.612,1.612,0,0,0,.32.277,3.461,3.461,0,0,0,.383.223q.2.1.312.144a5.182,5.182,0,0,0,.793.258q.418.1.856.168t.871.094Q7.1,14,7.5,14Z"/><rect class="cls-2" width="16" height="16"/></svg>
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
27
extensions/mssql/resources/database.svg
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="a96792b7-ce28-4ca3-9767-4e065ef4820f"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 18 18"
|
||||
style="enable-background:new 0 0 18 18;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:url(#SVGID_1_);}
|
||||
.st1{fill:#E8E8E8;}
|
||||
.st2{fill:#50E6FF;}
|
||||
.st3{fill:#198AB3;}
|
||||
</style>
|
||||
<title>Icon-databases-130</title>
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="2.59" y1="9.84" x2="15.41" y2="9.84" gradientTransform="matrix(1 0 0 -1 0 20)">
|
||||
<stop offset="0" style="stop-color:#005BA1"/>
|
||||
<stop offset="7.000000e-02" style="stop-color:#0060A9"/>
|
||||
<stop offset="0.36" style="stop-color:#0071C8"/>
|
||||
<stop offset="0.52" style="stop-color:#0078D4"/>
|
||||
<stop offset="0.64" style="stop-color:#0074CD"/>
|
||||
<stop offset="0.82" style="stop-color:#006ABB"/>
|
||||
<stop offset="1" style="stop-color:#005BA1"/>
|
||||
</linearGradient>
|
||||
<path class="st0" d="M9,5.1c-3.5,0-6.4-1-6.4-2.3v12.4c0,1.3,2.8,2.3,6.3,2.3H9c3.5,0,6.4-1,6.4-2.3V2.8C15.4,4.1,12.5,5.1,9,5.1z"
|
||||
/>
|
||||
<path class="st1" d="M15.4,2.8c0,1.3-2.9,2.3-6.4,2.3s-6.4-1-6.4-2.3S5.5,0.5,9,0.5S15.4,1.5,15.4,2.8"/>
|
||||
<path class="st2" d="M13.9,2.6c0,0.8-2.2,1.5-4.9,1.5S4.1,3.5,4.1,2.6S6.3,1.2,9,1.2S13.9,1.8,13.9,2.6"/>
|
||||
<path class="st3" d="M9,3C7.7,3,6.4,3.2,5.1,3.6C6.4,4,7.7,4.2,9,4.1c1.3,0,2.6-0.2,3.9-0.6C11.6,3.1,10.3,3,9,3z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -1 +0,0 @@
|
||||
<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:none;}</style></defs><title>bv</title><path d="M7.5,1q.563,0,1.246.062a10.962,10.962,0,0,1,1.367.215,7.406,7.406,0,0,1,1.3.418,3.558,3.558,0,0,1,1.039.664,1.991,1.991,0,0,1,.4.516A1.327,1.327,0,0,1,13,3.5v9a1.292,1.292,0,0,1-.152.629,2.2,2.2,0,0,1-.4.512,3.24,3.24,0,0,1-1.027.66,7.741,7.741,0,0,1-1.313.418,10.706,10.706,0,0,1-1.379.219Q8.047,15,7.5,15q-.562,0-1.246-.062a10.962,10.962,0,0,1-1.367-.215,7.323,7.323,0,0,1-1.3-.418,3.538,3.538,0,0,1-1.039-.664,1.958,1.958,0,0,1-.395-.516A1.322,1.322,0,0,1,2,12.5v-9a1.3,1.3,0,0,1,.152-.629,2.217,2.217,0,0,1,.4-.512A3.257,3.257,0,0,1,3.574,1.7a7.924,7.924,0,0,1,1.313-.418,10.883,10.883,0,0,1,1.379-.219Q6.953,1,7.5,1Zm0,1c-.266,0-.543.01-.832.027s-.579.05-.871.094-.577.1-.856.172a6.4,6.4,0,0,0-.793.254c-.078.031-.182.08-.312.144a3.808,3.808,0,0,0-.383.223,1.645,1.645,0,0,0-.32.277A.47.47,0,0,0,3,3.5a.3.3,0,0,0,.023.117.618.618,0,0,0,.063.11,1.445,1.445,0,0,0,.473.437,3.925,3.925,0,0,0,.695.328,6.414,6.414,0,0,0,.824.238q.438.1.871.157t.836.086Q7.189,5,7.5,5t.715-.027q.4-.027.836-.086t.871-.157a6.414,6.414,0,0,0,.824-.238,3.827,3.827,0,0,0,.692-.328,1.542,1.542,0,0,0,.476-.437.618.618,0,0,0,.063-.11A.3.3,0,0,0,12,3.5a.47.47,0,0,0-.133-.309,1.645,1.645,0,0,0-.32-.277,3.808,3.808,0,0,0-.383-.223c-.13-.064-.234-.113-.312-.144a6.4,6.4,0,0,0-.793-.254q-.418-.105-.856-.172t-.871-.094C8.043,2.01,7.766,2,7.5,2Zm0,12q.4,0,.832-.027t.871-.094q.438-.066.856-.168a5.182,5.182,0,0,0,.793-.258q.117-.046.312-.144a3.461,3.461,0,0,0,.383-.223,1.612,1.612,0,0,0,.32-.277A.47.47,0,0,0,12,12.5V4.984a4.572,4.572,0,0,1-1.008.485,8.312,8.312,0,0,1-1.168.312,11.149,11.149,0,0,1-1.207.168Q8.015,6,7.5,6T6.379,5.949a11.047,11.047,0,0,1-1.207-.168,8.368,8.368,0,0,1-1.164-.312A4.572,4.572,0,0,1,3,4.984V12.5a.47.47,0,0,0,.133.309,1.612,1.612,0,0,0,.32.277,3.461,3.461,0,0,0,.383.223q.2.1.312.144a5.182,5.182,0,0,0,.793.258q.418.1.856.168t.871.094Q7.1,14,7.5,14Z"/><rect class="cls-1" width="16" height="16"/></svg>
|
||||
|
Before Width: | Height: | Size: 2.0 KiB |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "azuredatastudio",
|
||||
"version": "1.17.0",
|
||||
"distro": "b5ba37f6b0c11bd7c826d81dec82c379633e0e27",
|
||||
"distro": "a7c650f63c6a601fb9431941301c78a7bce34ae3",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
},
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
"builtInExtensions": [
|
||||
{
|
||||
"name": "Microsoft.sqlservernotebook",
|
||||
"version": "0.3.5",
|
||||
"version": "0.3.6",
|
||||
"repo": "https://github.com/Microsoft/azuredatastudio"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -11,37 +11,33 @@ export async function openModelViewDashboard(context: vscode.ExtensionContext):
|
||||
dashboard.registerTabs(async (view: azdata.ModelView) => {
|
||||
// Tab with toolbar
|
||||
const button = view.modelBuilder.button().withProperties<azdata.ButtonProperties>({
|
||||
label: 'Run',
|
||||
label: 'Add databases tab',
|
||||
iconPath: {
|
||||
light: context.asAbsolutePath('images/compare.svg'),
|
||||
dark: context.asAbsolutePath('images/compare-inverse.svg')
|
||||
}
|
||||
}).component();
|
||||
|
||||
button.onDidClick(() => {
|
||||
vscode.window.showInformationMessage('Run button clicked');
|
||||
});
|
||||
|
||||
const toolbar = view.modelBuilder.toolbarContainer().withItems([button]).withLayout({
|
||||
orientation: azdata.Orientation.Horizontal
|
||||
}).component();
|
||||
|
||||
const textComponent1 = view.modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: 'text 1' }).component();
|
||||
const input1 = view.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({ value: 'input 1' }).component();
|
||||
const homeTab: azdata.DashboardTab = {
|
||||
id: 'home',
|
||||
toolbar: toolbar,
|
||||
content: textComponent1,
|
||||
content: input1,
|
||||
title: 'Home',
|
||||
icon: context.asAbsolutePath('images/home.svg') // icon can be the path of a svg file
|
||||
};
|
||||
|
||||
// Tab with nested tabbed Panel
|
||||
const textComponent2 = view.modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: 'text 2' }).component();
|
||||
const textComponent3 = view.modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: 'text 3' }).component();
|
||||
|
||||
const addTabButton = view.modelBuilder.button().withProperties<azdata.ButtonProperties>({ label: 'Add a tab', width: '150px' }).component();
|
||||
const removeTabButton = view.modelBuilder.button().withProperties<azdata.ButtonProperties>({ label: 'Remove a tab', width: '150px' }).component();
|
||||
const container = view.modelBuilder.flexContainer().withItems([addTabButton, removeTabButton]).withLayout({ flexFlow: 'column' }).component();
|
||||
const nestedTab1 = {
|
||||
title: 'Tab1',
|
||||
content: textComponent2,
|
||||
content: container,
|
||||
id: 'tab1',
|
||||
icon: {
|
||||
light: context.asAbsolutePath('images/user.svg'),
|
||||
@@ -49,9 +45,10 @@ export async function openModelViewDashboard(context: vscode.ExtensionContext):
|
||||
}
|
||||
};
|
||||
|
||||
const input2 = view.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({ value: 'input 2' }).component();
|
||||
const nestedTab2 = {
|
||||
title: 'Tab2',
|
||||
content: textComponent3,
|
||||
content: input2,
|
||||
icon: {
|
||||
light: context.asAbsolutePath('images/group.svg'),
|
||||
dark: context.asAbsolutePath('images/group_inverse.svg')
|
||||
@@ -59,6 +56,13 @@ export async function openModelViewDashboard(context: vscode.ExtensionContext):
|
||||
id: 'tab2'
|
||||
};
|
||||
|
||||
const input3 = view.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({ value: 'input 4' }).component();
|
||||
const nestedTab3 = {
|
||||
title: 'Tab3',
|
||||
content: input3,
|
||||
id: 'tab3'
|
||||
};
|
||||
|
||||
const tabbedPanel = view.modelBuilder.tabbedPanel().withTabs([
|
||||
nestedTab1, nestedTab2
|
||||
]).withLayout({
|
||||
@@ -66,6 +70,15 @@ export async function openModelViewDashboard(context: vscode.ExtensionContext):
|
||||
showIcon: true
|
||||
}).component();
|
||||
|
||||
|
||||
addTabButton.onDidClick(() => {
|
||||
tabbedPanel.updateTabs([nestedTab1, nestedTab2, nestedTab3]);
|
||||
});
|
||||
|
||||
removeTabButton.onDidClick(() => {
|
||||
tabbedPanel.updateTabs([nestedTab1, nestedTab3]);
|
||||
});
|
||||
|
||||
const settingsTab: azdata.DashboardTab = {
|
||||
id: 'settings',
|
||||
content: tabbedPanel,
|
||||
@@ -81,10 +94,23 @@ export async function openModelViewDashboard(context: vscode.ExtensionContext):
|
||||
]
|
||||
};
|
||||
|
||||
// Databases tab
|
||||
const databasesText = view.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({ value: 'This is databases tab', width: '200px' }).component();
|
||||
const databasesTab: azdata.DashboardTab = {
|
||||
id: 'databases',
|
||||
content: databasesText,
|
||||
title: 'Databases',
|
||||
icon: context.asAbsolutePath('images/default.svg')
|
||||
};
|
||||
button.onDidClick(() => {
|
||||
dashboard.updateTabs([homeTab, databasesTab, securityTabGroup]);
|
||||
});
|
||||
|
||||
return [
|
||||
homeTab,
|
||||
securityTabGroup
|
||||
];
|
||||
});
|
||||
dashboard.open();
|
||||
await dashboard.open();
|
||||
}
|
||||
|
||||
|
||||
7
src/sql/azdata.proposed.d.ts
vendored
@@ -210,6 +210,12 @@ declare module 'azdata' {
|
||||
* The event argument is the id of the selected tab.
|
||||
*/
|
||||
onTabChanged: vscode.Event<string>;
|
||||
|
||||
/**
|
||||
* update the tabs.
|
||||
* @param tabs new tabs
|
||||
*/
|
||||
updateTabs(tabs: (Tab | TabGroup)[]): void;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -310,6 +316,7 @@ declare module 'azdata' {
|
||||
export interface ModelViewDashboard {
|
||||
registerTabs(handler: (view: ModelView) => Thenable<(DashboardTab | DashboardTabGroup)[]>): void;
|
||||
open(): Thenable<void>;
|
||||
updateTabs(tabs: (DashboardTab | DashboardTabGroup)[]): void;
|
||||
}
|
||||
|
||||
export function createModelViewDashboard(title: string, options?: ModelViewDashboardOptions): ModelViewDashboard;
|
||||
|
||||
@@ -16,7 +16,7 @@ import { subscriptionToDisposable } from 'sql/base/browser/lifecycle';
|
||||
@Component({
|
||||
selector: 'breadcrumb',
|
||||
template: `
|
||||
<span style="display: flex; flex-flow: row; align-items: center; margin: 10px">
|
||||
<span class="breadcrumb-container">
|
||||
<ng-template ngFor let-item let-first="first" let-last="last" [ngForOf]="menuItems">
|
||||
<span style="padding: 5px; display: flex; align-items: center">
|
||||
<span *ngIf="item.icon" class="codicon" style="display: inline-block; margin-right: 5px" [ngClass]="item.icon"></span>
|
||||
|
||||
@@ -30,3 +30,11 @@ breadcrumb .chevron-right.codicon {
|
||||
breadcrumb .router-link {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
breadcrumb .breadcrumb-container {
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
align-items: center;
|
||||
margin: 10px;
|
||||
margin-left: 19px
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ panel {
|
||||
}
|
||||
|
||||
.tabbedPanel.vertical .tabList .tab .tabLabel {
|
||||
font-size: 12px;
|
||||
font-size: 13px;
|
||||
padding-bottom: 0px;
|
||||
font-weight: normal;
|
||||
}
|
||||
@@ -76,10 +76,16 @@ panel {
|
||||
min-width: 65px;
|
||||
}
|
||||
|
||||
.tabbedPanel.horizontal > .title .tabList .tab-header {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.tabbedPanel.vertical > .title .tabList .tab-header {
|
||||
display: block;
|
||||
min-width: 150px;
|
||||
line-height: 35px;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
}
|
||||
|
||||
.tabbedPanel .tabList .tab .tabIcon.codicon {
|
||||
@@ -152,13 +158,12 @@ panel {
|
||||
}
|
||||
|
||||
.tabbedPanel .tab-group-header {
|
||||
font-weight: bold;
|
||||
margin: 15px 5px 3px 5px;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
margin: 10px 24px 5px 24px;
|
||||
line-height: 35px;
|
||||
height: 35px;
|
||||
border-style: solid;
|
||||
border-width: 0 0 1px 0;
|
||||
border-color: rgb(214, 214, 214);
|
||||
}
|
||||
|
||||
.tabbedPanel .vertical-tab-action-container {
|
||||
|
||||
@@ -23,6 +23,9 @@ import * as nls from 'vs/nls';
|
||||
import { TabHeaderComponent } from 'sql/base/browser/ui/panel/tabHeader.component';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { IThemable } from 'vs/base/common/styler';
|
||||
import { ITabbedPanelStyles } from 'sql/base/browser/ui/panel/panel';
|
||||
import { createStyleSheet } from 'vs/base/browser/dom';
|
||||
|
||||
export interface IPanelOptions {
|
||||
/**
|
||||
@@ -49,7 +52,7 @@ let idPool = 0;
|
||||
@Component({
|
||||
selector: 'panel',
|
||||
template: `
|
||||
<div class="tabbedPanel fullsize" [ngClass]="options.layout === NavigationBarLayout.vertical ? 'vertical' : 'horizontal'">
|
||||
<div #rootContainer class="tabbedPanel fullsize" [ngClass]="options.layout === NavigationBarLayout.vertical ? 'vertical' : 'horizontal'">
|
||||
<div *ngIf="!options.alwaysShowTabs ? _tabs.length !== 1 : true" class="composite title">
|
||||
<div class="tabContainer">
|
||||
<div *ngIf="options.layout === NavigationBarLayout.vertical" class="vertical-tab-action-container">
|
||||
@@ -81,7 +84,7 @@ let idPool = 0;
|
||||
</div>
|
||||
`
|
||||
})
|
||||
export class PanelComponent extends Disposable {
|
||||
export class PanelComponent extends Disposable implements IThemable {
|
||||
@Input() public options?: IPanelOptions;
|
||||
@Input() public actions?: Array<Action>;
|
||||
@ContentChildren(TabComponent) private readonly _tabs!: QueryList<TabComponent>;
|
||||
@@ -95,12 +98,15 @@ export class PanelComponent extends Disposable {
|
||||
private _actionbar?: ActionBar;
|
||||
private _mru: TabComponent[] = [];
|
||||
private _tabExpanded: boolean = true;
|
||||
private _styleElement: HTMLStyleElement;
|
||||
|
||||
protected AutoScrollbarVisibility = ScrollbarVisibility.Auto; // used by angular template
|
||||
protected HiddenScrollbarVisibility = ScrollbarVisibility.Hidden; // used by angular template
|
||||
protected NavigationBarLayout = NavigationBarLayout; // used by angular template
|
||||
|
||||
@ViewChild('panelActionbar', { read: ElementRef }) private _actionbarRef!: ElementRef;
|
||||
@ViewChild('rootContainer', { read: ElementRef }) private _rootContainer!: ElementRef;
|
||||
|
||||
constructor(
|
||||
@Inject(forwardRef(() => NgZone)) private _zone: NgZone,
|
||||
@Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef) {
|
||||
@@ -122,6 +128,8 @@ export class PanelComponent extends Disposable {
|
||||
|
||||
ngOnInit(): void {
|
||||
this.options = mixin(this.options || {}, defaultOptions, false);
|
||||
const rootContainerElement = this._rootContainer.nativeElement as HTMLElement;
|
||||
this._styleElement = createStyleSheet(rootContainerElement);
|
||||
}
|
||||
|
||||
ngAfterContentInit(): void {
|
||||
@@ -321,4 +329,70 @@ export class PanelComponent extends Disposable {
|
||||
return header.nativeElement === document.activeElement;
|
||||
});
|
||||
}
|
||||
|
||||
style(styles: ITabbedPanelStyles) {
|
||||
if (this._styleElement) {
|
||||
const content: string[] = [];
|
||||
if (styles.titleInactiveForeground) {
|
||||
content.push(`.tabbedPanel.horizontal > .title .tabList .tab-header {
|
||||
color: ${styles.titleInactiveForeground}
|
||||
}`);
|
||||
}
|
||||
if (styles.titleActiveBorder && styles.titleActiveForeground) {
|
||||
content.push(`.tabbedPanel.horizontal > .title .tabList .tab-header:focus,
|
||||
.tabbedPanel.horizontal > .title .tabList .tab-header.active {
|
||||
border-color: ${styles.titleActiveBorder};
|
||||
border-style: solid;
|
||||
color: ${styles.titleActiveForeground}
|
||||
}`);
|
||||
|
||||
content.push(`.tabbedPanel.horizontal > .title .tabList .tab-header:focus,
|
||||
.tabbedPanel.horizontal > .title .tabList .tab-header.active {;
|
||||
border-width: 0 0 ${styles.activeTabContrastBorder ? '0' : '2'}px 0;
|
||||
}`);
|
||||
|
||||
content.push(`.tabbedPanel.horizontal > .title .tabList .tab-header:hover {
|
||||
color: ${styles.titleActiveForeground}
|
||||
}`);
|
||||
}
|
||||
|
||||
if (styles.activeBackgroundForVerticalLayout) {
|
||||
content.push(`.tabbedPanel.vertical > .title .tabList .tab-header.active {
|
||||
background-color:${styles.activeBackgroundForVerticalLayout}
|
||||
}`);
|
||||
}
|
||||
|
||||
if (styles.border) {
|
||||
content.push(`.tabbedPanel.vertical > .title > .tabContainer {
|
||||
border-right-width: 1px;
|
||||
border-right-style: solid;
|
||||
border-right-color: ${styles.border};
|
||||
}
|
||||
|
||||
.tabbedPanel .tab-group-header {
|
||||
border-color: ${styles.border};
|
||||
}`);
|
||||
}
|
||||
|
||||
if (styles.activeTabContrastBorder) {
|
||||
content.push(`
|
||||
.tabbedPanel > .title .tabList .tab-header.active {
|
||||
outline: 1px solid;
|
||||
outline-offset: -3px;
|
||||
outline-color: ${styles.activeTabContrastBorder};
|
||||
}
|
||||
`);
|
||||
} else {
|
||||
content.push(`.tabbedPanel.horizontal > .title .tabList .tab-header:focus {
|
||||
outline-width: 0px;
|
||||
}`);
|
||||
}
|
||||
|
||||
const newStyles = content.join('\n');
|
||||
if (newStyles !== this._styleElement.innerHTML) {
|
||||
this._styleElement.innerHTML = newStyles;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@ export interface ITabbedPanelStyles {
|
||||
titleInactiveForeground?: Color;
|
||||
focusBorder?: Color;
|
||||
outline?: Color;
|
||||
activeBackgroundForVerticalLayout?: Color;
|
||||
border?: Color;
|
||||
activeTabContrastBorder?: Color;
|
||||
}
|
||||
|
||||
export interface IPanelOptions {
|
||||
|
||||
@@ -19,7 +19,7 @@ import { CloseTabAction } from 'sql/base/browser/ui/panel/tabActions';
|
||||
@Component({
|
||||
selector: 'tab-header',
|
||||
template: `
|
||||
<div #actionHeader role="tab" [attr.aria-selected]="tab.active" [attr.aria-label]="tab.title" class="tab-header" style="flex: 0 0; flex-direction: row; height: 100%" [class.active]="tab.active" tabindex="0" (click)="selectTab(tab)" (keyup)="onKey($event)">
|
||||
<div #actionHeader role="tab" [attr.aria-selected]="tab.active" [attr.aria-label]="tab.title" class="tab-header" style="flex: 0 0; flex-direction: row;" [class.active]="tab.active" tabindex="0" (click)="selectTab(tab)" (keyup)="onKey($event)">
|
||||
<span class="tab" role="presentation">
|
||||
<div role="presentation">
|
||||
<a #tabIcon></a>
|
||||
|
||||
@@ -27,18 +27,18 @@ const defaultOptions: IActionBarOptions = {
|
||||
*/
|
||||
export class ActionBar extends ActionRunner implements IActionRunner {
|
||||
|
||||
private _options: IActionBarOptions;
|
||||
private _actionRunner: IActionRunner;
|
||||
private _context: any;
|
||||
protected _options: IActionBarOptions;
|
||||
protected _actionRunner: IActionRunner;
|
||||
protected _context: any;
|
||||
|
||||
// Items
|
||||
private _items: IActionViewItem[];
|
||||
private _focusedItem?: number;
|
||||
private _focusTracker: DOM.IFocusTracker;
|
||||
protected _items: IActionViewItem[];
|
||||
protected _focusedItem?: number;
|
||||
protected _focusTracker: DOM.IFocusTracker;
|
||||
|
||||
// Elements
|
||||
private _domNode: HTMLElement;
|
||||
private _actionsList: HTMLElement;
|
||||
protected _domNode: HTMLElement;
|
||||
protected _actionsList: HTMLElement;
|
||||
|
||||
constructor(container: HTMLElement, options: IActionBarOptions = defaultOptions) {
|
||||
super();
|
||||
@@ -128,6 +128,7 @@ export class ActionBar extends ActionRunner implements IActionRunner {
|
||||
this._actionsList = document.createElement('ul');
|
||||
this._actionsList.className = 'actions-container';
|
||||
this._actionsList.setAttribute('role', 'toolbar');
|
||||
this._actionsList.id = 'actions-container';
|
||||
if (this._options.ariaLabel) {
|
||||
this._actionsList.setAttribute('aria-label', this._options.ariaLabel);
|
||||
}
|
||||
@@ -145,7 +146,7 @@ export class ActionBar extends ActionRunner implements IActionRunner {
|
||||
}
|
||||
}
|
||||
|
||||
private updateFocusedItem(): void {
|
||||
protected updateFocusedItem(): void {
|
||||
let actionIndex = 0;
|
||||
for (let i = 0; i < this._actionsList.children.length; i++) {
|
||||
let elem = this._actionsList.children[i];
|
||||
@@ -155,7 +156,7 @@ export class ActionBar extends ActionRunner implements IActionRunner {
|
||||
break;
|
||||
}
|
||||
|
||||
if (elem.classList.contains('action-item')) {
|
||||
if (elem.classList.contains('action-item') && i !== this._actionsList.children.length - 1) {
|
||||
actionIndex++;
|
||||
}
|
||||
}
|
||||
@@ -268,7 +269,7 @@ export class ActionBar extends ActionRunner implements IActionRunner {
|
||||
this.updateFocus();
|
||||
}
|
||||
|
||||
private focusNext(): void {
|
||||
protected focusNext(): void {
|
||||
if (typeof this._focusedItem === 'undefined') {
|
||||
this._focusedItem = this._items.length - 1;
|
||||
}
|
||||
@@ -288,7 +289,7 @@ export class ActionBar extends ActionRunner implements IActionRunner {
|
||||
this.updateFocus();
|
||||
}
|
||||
|
||||
private focusPrevious(): void {
|
||||
protected focusPrevious(): void {
|
||||
if (typeof this._focusedItem === 'undefined') {
|
||||
this._focusedItem = 0;
|
||||
}
|
||||
@@ -313,7 +314,7 @@ export class ActionBar extends ActionRunner implements IActionRunner {
|
||||
this.updateFocus();
|
||||
}
|
||||
|
||||
private updateFocus(): void {
|
||||
protected updateFocus(): void {
|
||||
if (typeof this._focusedItem === 'undefined') {
|
||||
this._domNode.focus();
|
||||
return;
|
||||
@@ -329,7 +330,7 @@ export class ActionBar extends ActionRunner implements IActionRunner {
|
||||
actionItem.focus();
|
||||
}
|
||||
} else {
|
||||
if (types.isFunction(actionItem.blur)) {
|
||||
if (actionItem && types.isFunction(actionItem.blur)) {
|
||||
actionItem.blur();
|
||||
}
|
||||
}
|
||||
@@ -349,7 +350,7 @@ export class ActionBar extends ActionRunner implements IActionRunner {
|
||||
}
|
||||
}
|
||||
|
||||
private cancel(): void {
|
||||
protected cancel(): void {
|
||||
if (document.activeElement instanceof HTMLElement) {
|
||||
(<HTMLElement>document.activeElement).blur(); // remove focus from focussed action
|
||||
}
|
||||
|
||||
@@ -47,6 +47,10 @@
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.carbon-taskbar .action-item.more {
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
.carbon-taskbar .action-label {
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0% 50%;
|
||||
@@ -86,3 +90,52 @@
|
||||
.carbon-taskbar .codicon {
|
||||
background-size: 11px;
|
||||
}
|
||||
|
||||
.carbon-taskbar .overflow {
|
||||
position:absolute;
|
||||
right:0;
|
||||
display:none;
|
||||
z-index: 3;
|
||||
padding-left: 0;
|
||||
margin-top: 6px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.vs-dark .carbon-taskbar .overflow {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.hc-black .carbon-taskbar .overflow {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.carbon-taskbar .overflow li {
|
||||
padding: 5px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.carbon-taskbar .overflow li.focused a.action-label {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.carbon-taskbar .overflow a {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.carbon-taskbar .actions-container .action-item .action-label.moreActionsElement {
|
||||
height: 18px;
|
||||
margin-top: 3px;
|
||||
background-position: center;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.carbon-taskbar .overflow .action-item .action-label{
|
||||
background-size: 16px;
|
||||
background-position: left;
|
||||
}
|
||||
|
||||
.overflow .taskbarSeparator {
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
328
src/sql/base/browser/ui/taskbar/overflowActionbar.ts
Normal file
@@ -0,0 +1,328 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import 'sql/base/browser/ui/taskbar/overflowActionbarStyles';
|
||||
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import {
|
||||
IActionBarOptions, ActionsOrientation, IActionViewItem,
|
||||
IActionOptions
|
||||
} from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import * as nls from 'vs/nls';
|
||||
import { debounce } from 'vs/base/common/decorators';
|
||||
import { ActionBar } from 'sql/base/browser/ui/taskbar/actionbar';
|
||||
|
||||
const defaultOptions: IActionBarOptions = {
|
||||
orientation: ActionsOrientation.HORIZONTAL,
|
||||
context: null
|
||||
};
|
||||
|
||||
/**
|
||||
* Extends Actionbar so that it overflows when the window is resized to be smaller than the actionbar instead of wrapping
|
||||
*/
|
||||
export class OverflowActionBar extends ActionBar {
|
||||
// Elements
|
||||
private _overflow: HTMLElement;
|
||||
private _moreItemElement: HTMLElement;
|
||||
private _moreActionsElement: HTMLElement;
|
||||
|
||||
constructor(container: HTMLElement, options: IActionBarOptions = defaultOptions) {
|
||||
super(container, options);
|
||||
|
||||
this._register(DOM.addDisposableListener(window, DOM.EventType.RESIZE, e => {
|
||||
if (this._actionsList) {
|
||||
this.resizeToolbar();
|
||||
}
|
||||
}));
|
||||
|
||||
this._overflow = document.createElement('ul');
|
||||
this._overflow.id = 'overflow';
|
||||
this._overflow.className = 'overflow';
|
||||
this._overflow.setAttribute('role', 'menu');
|
||||
this._domNode.appendChild(this._overflow);
|
||||
|
||||
this._register(DOM.addDisposableListener(this._overflow, DOM.EventType.FOCUS_OUT, e => {
|
||||
if (this._overflow && !DOM.isAncestor(e.relatedTarget as HTMLElement, this._overflow) && e.relatedTarget !== this._moreActionsElement) {
|
||||
this.hideOverflowDisplay();
|
||||
}
|
||||
}));
|
||||
this._actionsList.style.flexWrap = 'nowrap';
|
||||
|
||||
container.appendChild(this._domNode);
|
||||
}
|
||||
|
||||
@debounce(300)
|
||||
private resizeToolbar() {
|
||||
let width = this._actionsList.offsetWidth;
|
||||
let fullWidth = this._actionsList.scrollWidth;
|
||||
|
||||
// collapse actions that are beyond the width of the toolbar
|
||||
if (width < fullWidth) {
|
||||
// create '•••' more element if it doesn't exist yet
|
||||
if (!this._moreItemElement) {
|
||||
this.createMoreItemElement();
|
||||
}
|
||||
|
||||
this._moreItemElement.style.display = 'block';
|
||||
while (width < fullWidth) {
|
||||
let index = this._actionsList.childNodes.length - 2; // remove the last toolbar action before the more actions '...'
|
||||
if (index > -1) {
|
||||
this.collapseItem();
|
||||
fullWidth = this._actionsList.scrollWidth;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (this._overflow?.hasChildNodes()) { // uncollapse actions if there is space for it
|
||||
while (width === fullWidth && this._overflow.hasChildNodes()) {
|
||||
// move placeholder in this._items
|
||||
let placeHolderItem = this._items.splice(this._actionsList.childNodes.length - 1, 1);
|
||||
this._items.splice(this._actionsList.childNodes.length, 0, placeHolderItem[0]);
|
||||
|
||||
let item = this._overflow.removeChild(this._overflow.firstChild);
|
||||
// change role back to button when it's in the toolbar
|
||||
if ((<HTMLElement>item).className !== 'taskbarSeparator') {
|
||||
(<HTMLElement>item.firstChild).setAttribute('role', 'button');
|
||||
}
|
||||
this._actionsList.insertBefore(item, this._actionsList.lastChild);
|
||||
|
||||
// if the action was too wide, collapse it again
|
||||
if (this._actionsList.scrollWidth > this._actionsList.offsetWidth) {
|
||||
// move placeholder in this._items
|
||||
this.collapseItem();
|
||||
break;
|
||||
} else if (!this._overflow.hasChildNodes()) {
|
||||
this._moreItemElement.style.display = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private collapseItem(): void {
|
||||
// move placeholder in this._items
|
||||
let placeHolderItem = this._items.splice(this._actionsList.childNodes.length - 1, 1);
|
||||
this._items.splice(this._actionsList.childNodes.length - 2, 0, placeHolderItem[0]);
|
||||
|
||||
let index = this._actionsList.childNodes.length - 2; // remove the last toolbar action before the more actions '...'
|
||||
let item = this._actionsList.removeChild(this._actionsList.childNodes[index]);
|
||||
this._overflow.insertBefore(item, this._overflow.firstChild);
|
||||
this._register(DOM.addDisposableListener(item, DOM.EventType.CLICK, (e => { this.hideOverflowDisplay(); })));
|
||||
|
||||
// change role to menuItem when it's in the overflow
|
||||
if ((<HTMLElement>this._overflow.firstChild).className !== 'taskbarSeparator') {
|
||||
(<HTMLElement>this._overflow.firstChild.firstChild).setAttribute('role', 'menuItem');
|
||||
}
|
||||
}
|
||||
|
||||
private createMoreItemElement(): void {
|
||||
this._moreItemElement = document.createElement('li');
|
||||
this._moreItemElement.className = 'action-item more';
|
||||
this._moreItemElement.setAttribute('role', 'presentation');
|
||||
this._moreActionsElement = document.createElement('a');
|
||||
this._moreActionsElement.className = 'moreActionsElement action-label codicon toggle-more';
|
||||
this._moreActionsElement.setAttribute('role', 'button');
|
||||
this._moreActionsElement.title = nls.localize('toggleMore', "Toggle More");
|
||||
this._moreActionsElement.tabIndex = 0;
|
||||
this._moreActionsElement.setAttribute('aria-haspopup', 'true');
|
||||
this._register(DOM.addDisposableListener(this._moreActionsElement, DOM.EventType.CLICK, (e => {
|
||||
this.moreElementOnClick(e);
|
||||
})));
|
||||
this._register(DOM.addDisposableListener(this._moreActionsElement, DOM.EventType.KEY_UP, (ev => {
|
||||
let event = new StandardKeyboardEvent(ev);
|
||||
if (event.keyCode === KeyCode.Enter || event.keyCode === KeyCode.Space) {
|
||||
this.moreElementOnClick(event);
|
||||
}
|
||||
})));
|
||||
|
||||
this._register(DOM.addDisposableListener(this._overflow, DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => {
|
||||
let event = new StandardKeyboardEvent(e);
|
||||
|
||||
// Close overflow if Escape is pressed
|
||||
if (event.equals(KeyCode.Escape)) {
|
||||
this.hideOverflowDisplay();
|
||||
this._moreActionsElement.focus();
|
||||
} else if (event.equals(KeyCode.UpArrow)) {
|
||||
// up arrow on first element in overflow should move focus to the bottom of the overflow
|
||||
if (this._focusedItem === this._actionsList.childElementCount) {
|
||||
this._focusedItem = this._actionsList.childElementCount + this._overflow.childElementCount - 2;
|
||||
this.updateFocus();
|
||||
} else {
|
||||
this.focusPrevious();
|
||||
}
|
||||
} else if (event.equals(KeyCode.DownArrow)) {
|
||||
// down arrow on last element should move focus to the first element of the overflow
|
||||
if (this._focusedItem === this._actionsList.childNodes.length + this._overflow.childNodes.length - 2) {
|
||||
this._focusedItem = this._actionsList.childElementCount;
|
||||
this.updateFocus();
|
||||
} else {
|
||||
this.focusNext();
|
||||
}
|
||||
} else if (event.equals(KeyMod.Shift | KeyCode.Tab)) {
|
||||
this.hideOverflowDisplay();
|
||||
this._focusedItem = this._actionsList.childElementCount - 1;
|
||||
this.updateFocus();
|
||||
} else if (event.equals(KeyCode.Tab)) {
|
||||
this.hideOverflowDisplay();
|
||||
}
|
||||
DOM.EventHelper.stop(event, true);
|
||||
}));
|
||||
|
||||
this._moreItemElement.appendChild(this._moreActionsElement);
|
||||
this._actionsList.appendChild(this._moreItemElement);
|
||||
this._items.push(undefined); // add place holder for more item element
|
||||
}
|
||||
|
||||
private moreElementOnClick(event: MouseEvent | StandardKeyboardEvent): void {
|
||||
this._overflow.style.display = this._overflow.style.display === 'block' ? 'none' : 'block';
|
||||
if (this._overflow.style.display === 'block') {
|
||||
this._focusedItem = this._actionsList.childElementCount;
|
||||
this.updateFocus();
|
||||
}
|
||||
DOM.EventHelper.stop(event, true);
|
||||
}
|
||||
|
||||
private hideOverflowDisplay(): void {
|
||||
this._overflow.style.display = 'none';
|
||||
this._focusedItem = this._actionsList.childElementCount - 1;
|
||||
}
|
||||
|
||||
protected updateFocusedItem(): void {
|
||||
let actionIndex = 0;
|
||||
for (let i = 0; i < this._actionsList.children.length; i++) {
|
||||
let elem = this._actionsList.children[i];
|
||||
|
||||
if (DOM.isAncestor(document.activeElement, elem)) {
|
||||
this._focusedItem = actionIndex;
|
||||
break;
|
||||
}
|
||||
|
||||
if (elem.classList.contains('action-item') && i !== this._actionsList.children.length - 1) {
|
||||
actionIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// move focus to overflow items if there are any
|
||||
if (this._overflow) {
|
||||
for (let i = 0; i < this._overflow.children.length; i++) {
|
||||
let elem = this._overflow.children[i];
|
||||
|
||||
if (DOM.isAncestor(document.activeElement, elem)) {
|
||||
this._focusedItem = actionIndex;
|
||||
break;
|
||||
}
|
||||
|
||||
if (elem.classList.contains('action-item')) {
|
||||
actionIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Push an HTML Element onto the action bar UI in the position specified by options.
|
||||
* Pushes to the last position if no options are provided.
|
||||
*/
|
||||
public pushElement(element: HTMLElement, options: IActionOptions = {}): void {
|
||||
super.pushElement(element, options);
|
||||
this.resizeToolbar();
|
||||
}
|
||||
|
||||
/**
|
||||
* Push an action onto the action bar UI in the position specified by options.
|
||||
* Pushes to the last position if no options are provided.
|
||||
*/
|
||||
public pushAction(arg: IAction | IAction[], options: IActionOptions = {}): void {
|
||||
super.pushAction(arg, options);
|
||||
this.resizeToolbar();
|
||||
}
|
||||
|
||||
protected focusNext(): void {
|
||||
if (typeof this._focusedItem === 'undefined') {
|
||||
this._focusedItem = this._items.length - 1;
|
||||
}
|
||||
|
||||
let startIndex = this._focusedItem;
|
||||
let item: IActionViewItem;
|
||||
|
||||
do {
|
||||
this._focusedItem = (this._focusedItem + 1) % this._items.length;
|
||||
item = this._items[this._focusedItem];
|
||||
} while (this._focusedItem !== startIndex && item && !item.isEnabled());
|
||||
|
||||
if (this._focusedItem === startIndex && item && !item.isEnabled()) {
|
||||
this._focusedItem = undefined;
|
||||
}
|
||||
|
||||
this.updateFocus();
|
||||
}
|
||||
|
||||
protected focusPrevious(): void {
|
||||
if (typeof this._focusedItem === 'undefined') {
|
||||
this._focusedItem = 0;
|
||||
}
|
||||
|
||||
let startIndex = this._focusedItem;
|
||||
let item: IActionViewItem;
|
||||
|
||||
do {
|
||||
this._focusedItem = this._focusedItem - 1;
|
||||
|
||||
if (this._focusedItem < 0) {
|
||||
this._focusedItem = this._items.length - 1;
|
||||
}
|
||||
|
||||
item = this._items[this._focusedItem];
|
||||
} while (this._focusedItem !== startIndex && item && !item.isEnabled());
|
||||
|
||||
if (this._focusedItem === startIndex && item && !item.isEnabled()) {
|
||||
this._focusedItem = undefined;
|
||||
}
|
||||
|
||||
this.updateFocus();
|
||||
}
|
||||
|
||||
protected updateFocus(): void {
|
||||
if (typeof this._focusedItem === 'undefined') {
|
||||
this._domNode.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < this._items.length; i++) {
|
||||
let item = this._items[i];
|
||||
|
||||
let actionItem = <any>item;
|
||||
|
||||
if (i === this._focusedItem) {
|
||||
// placeholder for location of moreActionsElement
|
||||
if (!actionItem) {
|
||||
this._moreActionsElement.focus();
|
||||
}
|
||||
else if (types.isFunction(actionItem.focus)) {
|
||||
actionItem.focus();
|
||||
}
|
||||
} else {
|
||||
if (actionItem && types.isFunction(actionItem.blur)) {
|
||||
actionItem.blur();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected cancel(): void {
|
||||
super.cancel();
|
||||
|
||||
if (this._overflow) {
|
||||
this.hideOverflowDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
public run(action: IAction, context?: any): Promise<any> {
|
||||
this.hideOverflowDisplay();
|
||||
return this._actionRunner.run(action, context);
|
||||
}
|
||||
}
|
||||
43
src/sql/base/browser/ui/taskbar/overflowActionbarStyles.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
// eslint-disable-next-line code-import-patterns
|
||||
import { registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
|
||||
// eslint-disable-next-line code-import-patterns
|
||||
import { EDITOR_PANE_BACKGROUND, DASHBOARD_BORDER, TOOLBAR_OVERFLOW_SHADOW } from 'vs/workbench/common/theme';
|
||||
// eslint-disable-next-line code-import-patterns
|
||||
import { focusBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
|
||||
registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => {
|
||||
const overflowBackground = theme.getColor(EDITOR_PANE_BACKGROUND);
|
||||
if (overflowBackground) {
|
||||
collector.addRule(`.carbon-taskbar .overflow {
|
||||
background-color: ${overflowBackground};
|
||||
}`);
|
||||
}
|
||||
|
||||
const overflowShadow = theme.getColor(TOOLBAR_OVERFLOW_SHADOW);
|
||||
if (overflowShadow) {
|
||||
collector.addRule(`.carbon-taskbar .overflow {
|
||||
box-shadow: 0px 4px 4px ${overflowShadow};
|
||||
}`);
|
||||
}
|
||||
|
||||
const border = theme.getColor(DASHBOARD_BORDER);
|
||||
if (border) {
|
||||
collector.addRule(`.carbon-taskbar .overflow {
|
||||
border: 1px solid ${border};
|
||||
}`);
|
||||
}
|
||||
|
||||
const activeOutline = theme.getColor(focusBorder);
|
||||
if (activeOutline) {
|
||||
collector.addRule(`.carbon-taskbar .overflow li.focused {
|
||||
outline: 1px solid;
|
||||
outline-offset: -3px;
|
||||
outline-color: ${activeOutline}
|
||||
}`);
|
||||
}
|
||||
});
|
||||
@@ -11,6 +11,7 @@ import { ActionBar } from './actionbar';
|
||||
import { IActionRunner, IAction } from 'vs/base/common/actions';
|
||||
import { ActionsOrientation, IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IToolBarOptions } from 'vs/base/browser/ui/toolbar/toolbar';
|
||||
import { OverflowActionBar } from 'sql/base/browser/ui/taskbar/overflowActionbar';
|
||||
|
||||
/**
|
||||
* A wrapper for the different types of content a QueryTaskbar can display
|
||||
@@ -33,20 +34,36 @@ export class Taskbar {
|
||||
private options: IToolBarOptions;
|
||||
private actionBar: ActionBar;
|
||||
|
||||
constructor(container: HTMLElement, options: IToolBarOptions = { orientation: ActionsOrientation.HORIZONTAL }) {
|
||||
constructor(container: HTMLElement, options: IToolBarOptions = { orientation: ActionsOrientation.HORIZONTAL }, collapseOverflow: boolean = false) {
|
||||
this.options = options;
|
||||
|
||||
let element = document.createElement('div');
|
||||
element.className = 'monaco-toolbar carbon-taskbar';
|
||||
container.appendChild(element);
|
||||
|
||||
this.actionBar = new ActionBar(element, {
|
||||
orientation: options.orientation,
|
||||
ariaLabel: options.ariaLabel,
|
||||
actionViewItemProvider: (action: IAction): IActionViewItem | undefined => {
|
||||
return options.actionViewItemProvider ? options.actionViewItemProvider(action) : undefined;
|
||||
}
|
||||
});
|
||||
if (collapseOverflow) {
|
||||
this.actionBar = new OverflowActionBar(
|
||||
element,
|
||||
{
|
||||
orientation: options.orientation,
|
||||
ariaLabel: options.ariaLabel,
|
||||
actionViewItemProvider: (action: IAction): IActionViewItem | undefined => {
|
||||
return options.actionViewItemProvider ? options.actionViewItemProvider(action) : undefined;
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
this.actionBar = new ActionBar(
|
||||
element,
|
||||
{
|
||||
orientation: options.orientation,
|
||||
ariaLabel: options.ariaLabel,
|
||||
actionViewItemProvider: (action: IAction): IActionViewItem | undefined => {
|
||||
return options.actionViewItemProvider ? options.actionViewItemProvider(action) : undefined;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -495,29 +495,33 @@ class ToolbarContainerBuilder extends GenericContainerBuilder<azdata.ToolbarCont
|
||||
|
||||
class TabbedPanelComponentBuilder extends ContainerBuilderImpl<azdata.TabbedPanelComponent, azdata.TabbedPanelLayout, any> implements azdata.TabbedPanelComponentBuilder {
|
||||
withTabs(items: (azdata.Tab | azdata.TabGroup)[]): azdata.ContainerBuilder<azdata.TabbedPanelComponent, azdata.TabbedPanelLayout, any> {
|
||||
const itemConfigs = [];
|
||||
items.forEach(item => {
|
||||
if (item && 'tabs' in item) {
|
||||
item.tabs.forEach(tab => {
|
||||
itemConfigs.push(this.toItemConfig(tab.content, tab.title, tab.id, item.title, tab.icon));
|
||||
});
|
||||
} else {
|
||||
const tab = <azdata.Tab>item;
|
||||
itemConfigs.push(this.toItemConfig(tab.content, tab.title, tab.id, undefined, tab.icon));
|
||||
}
|
||||
});
|
||||
this._component.itemConfigs = itemConfigs;
|
||||
this._component.itemConfigs = createFromTabs(items);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
toItemConfig(content: azdata.Component, title: string, id?: string, group?: string, icon?: string | URI | { light: string | URI; dark: string | URI }): InternalItemConfig {
|
||||
return new InternalItemConfig(content as ComponentWrapper, {
|
||||
title: title,
|
||||
group: group,
|
||||
id: id,
|
||||
icon: icon
|
||||
});
|
||||
}
|
||||
function createFromTabs(items: (azdata.Tab | azdata.TabGroup)[]): InternalItemConfig[] {
|
||||
const itemConfigs = [];
|
||||
items.forEach(item => {
|
||||
if (item && 'tabs' in item) {
|
||||
item.tabs.forEach(tab => {
|
||||
itemConfigs.push(toTabItemConfig(tab.content, tab.title, tab.id, item.title, tab.icon));
|
||||
});
|
||||
} else {
|
||||
const tab = <azdata.Tab>item;
|
||||
itemConfigs.push(toTabItemConfig(tab.content, tab.title, tab.id, undefined, tab.icon));
|
||||
}
|
||||
});
|
||||
return itemConfigs;
|
||||
}
|
||||
|
||||
function toTabItemConfig(content: azdata.Component, title: string, id?: string, group?: string, icon?: string | URI | { light: string | URI; dark: string | URI }): InternalItemConfig {
|
||||
return new InternalItemConfig(content as ComponentWrapper, {
|
||||
title: title,
|
||||
group: group,
|
||||
id: id,
|
||||
icon: icon
|
||||
});
|
||||
}
|
||||
|
||||
class LoadingComponentBuilder extends ComponentBuilderImpl<azdata.LoadingComponent> implements azdata.LoadingComponentBuilder {
|
||||
@@ -1728,6 +1732,13 @@ class TabbedPanelComponentWrapper extends ComponentWrapper implements azdata.Tab
|
||||
this.properties = {};
|
||||
this._emitterMap.set(ComponentEventType.onDidChange, new Emitter<string>());
|
||||
}
|
||||
updateTabs(tabs: (azdata.Tab | azdata.TabGroup)[]): void {
|
||||
this.clearItems();
|
||||
const itemConfigs = createFromTabs(tabs);
|
||||
itemConfigs.forEach(itemConfig => {
|
||||
this.addItem(itemConfig.component, itemConfig.config);
|
||||
});
|
||||
}
|
||||
|
||||
public get onTabChanged(): vscode.Event<string> {
|
||||
let emitter = this._emitterMap.get(ComponentEventType.onDidChange);
|
||||
|
||||
@@ -458,34 +458,34 @@ class WizardImpl implements azdata.window.Wizard {
|
||||
}
|
||||
|
||||
class ModelViewDashboardImpl implements azdata.window.ModelViewDashboard {
|
||||
private _tabbedPanel: azdata.TabbedPanelComponent;
|
||||
private _view: azdata.ModelView;
|
||||
|
||||
constructor(
|
||||
private _editor: ModelViewEditorImpl,
|
||||
private _options?: azdata.ModelViewDashboardOptions
|
||||
) {
|
||||
}
|
||||
|
||||
updateTabs(tabs: (azdata.DashboardTab | azdata.DashboardTabGroup)[]): void {
|
||||
if (this._tabbedPanel === undefined || this._view === undefined) {
|
||||
throw new Error(nls.localize('dashboardNotInitialized', "Tabs are not initialized"));
|
||||
}
|
||||
|
||||
this._tabbedPanel.updateTabs(this.createTabs(tabs, this._view));
|
||||
}
|
||||
|
||||
registerTabs(handler: (view: azdata.ModelView) => Thenable<(azdata.DashboardTab | azdata.DashboardTabGroup)[]>): void {
|
||||
this._editor.registerContent(async (view) => {
|
||||
this._view = view;
|
||||
const dashboardTabs = await handler(view);
|
||||
const tabs: (azdata.TabGroup | azdata.Tab)[] = [];
|
||||
dashboardTabs.forEach((item: azdata.DashboardTab | azdata.DashboardTabGroup) => {
|
||||
if ('tabs' in item) {
|
||||
tabs.push(<azdata.TabGroup>{
|
||||
title: item.title,
|
||||
tabs: item.tabs.map(tab => {
|
||||
return this.createTab(tab, view);
|
||||
})
|
||||
});
|
||||
} else {
|
||||
tabs.push(this.createTab(item, view));
|
||||
}
|
||||
});
|
||||
|
||||
const tabbedPanel = view.modelBuilder.tabbedPanel().withTabs(tabs).withLayout({
|
||||
const tabs = this.createTabs(dashboardTabs, view);
|
||||
this._tabbedPanel = view.modelBuilder.tabbedPanel().withTabs(tabs).withLayout({
|
||||
orientation: 'vertical',
|
||||
showIcon: this._options?.showIcon ?? true,
|
||||
alwaysShowTabs: this._options?.alwaysShowTabs ?? false
|
||||
}).component();
|
||||
return view.initializeModel(tabbedPanel);
|
||||
return view.initializeModel(this._tabbedPanel);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -508,6 +508,23 @@ class ModelViewDashboardImpl implements azdata.window.ModelViewDashboard {
|
||||
return tab;
|
||||
}
|
||||
}
|
||||
|
||||
createTabs(dashboardTabs: (azdata.DashboardTab | azdata.DashboardTabGroup)[], view: azdata.ModelView): (azdata.TabGroup | azdata.Tab)[] {
|
||||
const tabs: (azdata.TabGroup | azdata.Tab)[] = [];
|
||||
dashboardTabs.forEach((item: azdata.DashboardTab | azdata.DashboardTabGroup) => {
|
||||
if ('tabs' in item) {
|
||||
tabs.push(<azdata.TabGroup>{
|
||||
title: item.title,
|
||||
tabs: item.tabs.map(tab => {
|
||||
return this.createTab(tab, view);
|
||||
})
|
||||
});
|
||||
} else {
|
||||
tabs.push(this.createTab(item, view));
|
||||
}
|
||||
});
|
||||
return tabs;
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostModelViewDialog implements ExtHostModelViewDialogShape {
|
||||
|
||||
@@ -352,6 +352,7 @@ export abstract class ContainerBase<T> extends ComponentBase {
|
||||
|
||||
public clearContainer(): void {
|
||||
this.items = [];
|
||||
this.onItemsUpdated();
|
||||
this._changeRef.detectChanges();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,49 +11,3 @@
|
||||
.tabbedpanel-component .tabbedPanel {
|
||||
border-top-width: 0px;
|
||||
}
|
||||
|
||||
.tabbedpanel-component .tabbedPanel .tabContainer {
|
||||
border-style: solid;
|
||||
border-color: rgb(237, 235, 233);
|
||||
border-width: 0px;
|
||||
}
|
||||
|
||||
.vs-dark .tabbedpanel-component .tabbedPanel .tabContainer,
|
||||
.hc-black .tabbedpanel-component .tabbedPanel .tabContainer {
|
||||
border-color: rgba(128, 128, 128, 0.5);
|
||||
}
|
||||
|
||||
.tabbedpanel-component .tabbedPanel.vertical > .title .tabContainer {
|
||||
border-right-width: 1px;
|
||||
}
|
||||
|
||||
.tabbedpanel-component .tabbedPanel.horizontal > .title .tabContainer {
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
.tabbedpanel-component .tabbedPanel .tab > .tabLabel.active {
|
||||
border-bottom: 0px solid;
|
||||
}
|
||||
|
||||
.tabbedpanel-component .tabbedPanel.vertical .tabList .tab-header {
|
||||
line-height: 35px;
|
||||
}
|
||||
|
||||
.tabbedpanel-component .tabbedPanel.horizontal .tabList .tab-header {
|
||||
border-color: rgb(214, 214, 214);
|
||||
border-width: 0 1px 0 0;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
.tabbedpanel-component .tabbedPanel .tabList .tab .tabLabel {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.tabbedpanel-component .tabList .tab-header.active {
|
||||
background-color: #E1F0FE;
|
||||
}
|
||||
|
||||
.vs-dark .tabbedpanel-component .tabList .tab-header.active,
|
||||
.hc-black .tabbedpanel-component .tabList .tab-header.active {
|
||||
background-color: rgba(128, 128, 128, 0.5);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ import { ContainerBase } from 'sql/workbench/browser/modelComponents/componentBa
|
||||
import { ComponentEventType, IComponent, IComponentDescriptor, IModelStore } from 'sql/platform/dashboard/browser/interfaces';
|
||||
import 'vs/css!./media/tabbedPanel';
|
||||
import { IUserFriendlyIcon, createIconCssClass } from 'sql/workbench/browser/modelComponents/iconUtils';
|
||||
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||
import { attachTabbedPanelStyler } from 'sql/workbench/common/styler';
|
||||
|
||||
export interface TabConfig {
|
||||
title: string;
|
||||
@@ -40,7 +42,9 @@ export default class TabbedPanelComponent extends ContainerBase<TabConfig> imple
|
||||
|
||||
constructor(
|
||||
@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef,
|
||||
@Inject(forwardRef(() => ElementRef)) el: ElementRef) {
|
||||
@Inject(forwardRef(() => ElementRef)) el: ElementRef,
|
||||
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService
|
||||
) {
|
||||
super(changeRef, el);
|
||||
}
|
||||
|
||||
@@ -49,6 +53,7 @@ export default class TabbedPanelComponent extends ContainerBase<TabConfig> imple
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this._register(attachTabbedPanelStyler(this._panel, this.themeService));
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
@@ -99,7 +104,12 @@ export default class TabbedPanelComponent extends ContainerBase<TabConfig> imple
|
||||
}
|
||||
|
||||
onItemsUpdated(): void {
|
||||
const firstTabIndex = this.tabs.findIndex(tab => tab.type === 'tab');
|
||||
if (this.items.length === 0) {
|
||||
this._itemIndexToProcess = 0;
|
||||
this._tabs = [];
|
||||
}
|
||||
|
||||
const firstTabIndex = this._tabs.findIndex(tab => tab.type === 'tab');
|
||||
if (firstTabIndex >= 0) {
|
||||
this._panel.selectTab(firstTabIndex);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,11 @@ import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import * as cr from 'vs/platform/theme/common/colorRegistry';
|
||||
import { IThemable } from 'vs/base/common/styler';
|
||||
import { attachStyler } from 'vs/platform/theme/common/styler';
|
||||
import { SIDE_BAR_SECTION_HEADER_FOREGROUND, SIDE_BAR_BACKGROUND, SIDE_BAR_SECTION_HEADER_BACKGROUND, SIDE_BAR_DRAG_AND_DROP_BACKGROUND, PANEL_ACTIVE_TITLE_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND } from 'vs/workbench/common/theme';
|
||||
import {
|
||||
SIDE_BAR_SECTION_HEADER_FOREGROUND, SIDE_BAR_BACKGROUND, SIDE_BAR_SECTION_HEADER_BACKGROUND, SIDE_BAR_DRAG_AND_DROP_BACKGROUND,
|
||||
PANEL_ACTIVE_TITLE_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, VERTICAL_TAB_ACTIVE_BACKGROUND, DASHBOARD_BORDER,
|
||||
|
||||
} from 'vs/workbench/common/theme';
|
||||
|
||||
export function attachModalDialogStyler(widget: IThemable, themeService: IThemeService, style?:
|
||||
{
|
||||
@@ -39,6 +43,9 @@ export function attachTabbedPanelStyler(widget: IThemable, themeService: IThemeS
|
||||
titleActiveBorder: PANEL_ACTIVE_TITLE_BORDER,
|
||||
titleInactiveForeground: PANEL_INACTIVE_TITLE_FOREGROUND,
|
||||
focusBorder: cr.focusBorder,
|
||||
outline: cr.activeContrastBorder
|
||||
outline: cr.activeContrastBorder,
|
||||
activeBackgroundForVerticalLayout: VERTICAL_TAB_ACTIVE_BACKGROUND,
|
||||
border: DASHBOARD_BORDER,
|
||||
activeTabContrastBorder: cr.activeContrastBorder
|
||||
}, widget);
|
||||
}
|
||||
|
||||
@@ -129,6 +129,7 @@ export class DashboardWidgetWrapper extends AngularDisposable implements OnInit
|
||||
this._collapseAction = this.instantiationService.createInstance(CollapseWidgetAction, this._bootstrap.getUnderlyingUri(), this.guid, this.collapsed);
|
||||
if (this.bottomCollapse) {
|
||||
this._bottomActionbar.push(this._collapseAction, { icon: true, label: false });
|
||||
this._bottomActionbarRef.nativeElement.style.display = 'block';
|
||||
} else {
|
||||
this._actionbar.push(this._collapseAction, { icon: true, label: false });
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@ dashboard-widget-wrapper .widgetHeader {
|
||||
display: flex;
|
||||
flex: 0 0;
|
||||
padding: 3px 0 3px 0;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
dashboard-widget-wrapper .icon {
|
||||
@@ -44,5 +47,6 @@ dashboard-widget-wrapper .actionbar {
|
||||
dashboard-widget-wrapper .bottomActionbar {
|
||||
flex: 0 0 auto;
|
||||
align-self: center;
|
||||
margin-top: -28px;
|
||||
margin-top: -27px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ import { NAV_SECTION } from 'sql/workbench/contrib/dashboard/browser/containers/
|
||||
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||
import { DASHBOARD_BORDER } from 'vs/workbench/common/theme';
|
||||
import { IColorTheme } from 'vs/platform/theme/common/themeService';
|
||||
import { attachTabbedPanelStyler } from 'sql/workbench/common/styler';
|
||||
|
||||
|
||||
const dashboardRegistry = Registry.as<IDashboardRegistry>(DashboardExtensions.DashboardContributions);
|
||||
@@ -132,6 +133,7 @@ export abstract class DashboardPage extends AngularDisposable implements IConfig
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
attachTabbedPanelStyler(this._panel, this.themeService);
|
||||
this.updateTheme(this.themeService.getColorTheme());
|
||||
}
|
||||
|
||||
@@ -202,7 +204,7 @@ export abstract class DashboardPage extends AngularDisposable implements IConfig
|
||||
private createToolbar(parentElement: HTMLElement, tabId: string): void {
|
||||
// clear out toolbar
|
||||
DOM.clearNode(parentElement);
|
||||
this.toolbar = this._register(new Taskbar(parentElement, { actionViewItemProvider: action => this.createActionItemProvider(action as Action) }));
|
||||
this.toolbar = this._register(new Taskbar(parentElement, { actionViewItemProvider: action => this.createActionItemProvider(action as Action) }, true));
|
||||
let content = [];
|
||||
content = this.getToolbarContent(tabId);
|
||||
if (tabId === this.homeTabId) {
|
||||
|
||||
@@ -28,20 +28,10 @@ dashboard-page .home-tab-icon {
|
||||
background-image: url("media/home.svg");
|
||||
}
|
||||
|
||||
.vs-dark dashboard-page .home-tab-icon,
|
||||
.hc-black dashboard-page .home-tab-icon {
|
||||
background-image: url("media/home_inverse.svg");
|
||||
}
|
||||
|
||||
dashboard-page .default-tab-icon {
|
||||
background-image: url("media/default.svg");
|
||||
}
|
||||
|
||||
.vs-dark dashboard-page .default-tab-icon,
|
||||
.hc-black dashboard-page .default-tab-icon {
|
||||
background-image: url("media/default_inverse.svg");
|
||||
}
|
||||
|
||||
dashboard-page .actions-container .action-item .action-label{
|
||||
padding-left: 20px;
|
||||
padding-right: 5px;
|
||||
|
||||
@@ -5,20 +5,4 @@
|
||||
|
||||
panel.dashboard-panel > .tabbedPanel {
|
||||
border-top-width: 0px;
|
||||
border-top-style: solid;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header .tab > .tabLabel.active {
|
||||
border-bottom: 0px solid;
|
||||
}
|
||||
|
||||
panel.dashboard-panel > .tabbedPanel .tabList .tab .tabLabel {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
panel.dashboard-panel > .tabbedPanel > .title > .title-actions,
|
||||
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header {
|
||||
box-sizing: border-box;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
@@ -5,124 +5,38 @@
|
||||
|
||||
import 'vs/css!./dashboardPanel';
|
||||
import { registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
|
||||
import {
|
||||
TAB_ACTIVE_BACKGROUND, TAB_ACTIVE_FOREGROUND, TAB_INACTIVE_BACKGROUND,
|
||||
TAB_INACTIVE_FOREGROUND, EDITOR_GROUP_HEADER_TABS_BACKGROUND, TAB_BORDER, EDITOR_GROUP_BORDER, DASHBOARD_TAB_ACTIVE_BACKGROUND, DASHBOARD_BORDER
|
||||
} from 'vs/workbench/common/theme';
|
||||
import { activeContrastBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { DASHBOARD_WIDGET_SUBTEXT, TAB_LABEL, DASHBOARD_WIDGET_TITLE, DASHBOARD_PROPERTIES_NAME } from 'vs/workbench/common/theme';
|
||||
|
||||
registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => {
|
||||
// Title Active
|
||||
const tabActiveBackground = theme.getColor(TAB_ACTIVE_BACKGROUND);
|
||||
const tabActiveForeground = theme.getColor(TAB_ACTIVE_FOREGROUND);
|
||||
let tabActiveBackgroundVertical = theme.getColor(DASHBOARD_TAB_ACTIVE_BACKGROUND);
|
||||
|
||||
if (tabActiveBackground || tabActiveForeground) {
|
||||
collector.addRule(`
|
||||
panel.dashboard-panel > .tabbedPanel > .title .tabList .tab:hover .tabLabel,
|
||||
panel.dashboard-panel > .tabbedPanel > .title .tabList .tab .tabLabel.active {
|
||||
color: ${tabActiveForeground};
|
||||
border-bottom: 0px solid;
|
||||
}
|
||||
|
||||
panel.dashboard-panel > .tabbedPanel.vertical > .title .tabList .tab-header.active {
|
||||
background-color: ${tabActiveBackgroundVertical};
|
||||
}
|
||||
|
||||
panel.dashboard-panel > .tabbedPanel.horizontal > .title .tabList .tab-header.active {
|
||||
background-color: ${tabActiveBackground};
|
||||
}
|
||||
|
||||
panel.dashboard-panel > .tabbedPanel.horizontal > .title .tabList .tab-header.active {
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
panel.dashboard-panel > .tabbedPanel.vertical > .title .tabList .tab-header.active {
|
||||
border-right-color: transparent;
|
||||
}
|
||||
`);
|
||||
// tab label
|
||||
const tabLabelColor = theme.getColor(TAB_LABEL);
|
||||
if (tabLabelColor) {
|
||||
collector.addRule(`properties-widget .propertiesValue {
|
||||
color: ${tabLabelColor}
|
||||
}`);
|
||||
}
|
||||
|
||||
const highContrastActiveTabBorderColor = theme.getColor(activeContrastBorder);
|
||||
if (highContrastActiveTabBorderColor) {
|
||||
collector.addRule(`
|
||||
panel.dashboard-panel > .tabbedPanel > .title .tabList .tab-header.active {
|
||||
outline: 1px solid;
|
||||
outline-offset: -3px;
|
||||
outline-color: ${highContrastActiveTabBorderColor};
|
||||
}
|
||||
`);
|
||||
// widget title
|
||||
const widgetTitle = theme.getColor(DASHBOARD_WIDGET_TITLE);
|
||||
if (widgetTitle) {
|
||||
collector.addRule(`dashboard-widget-wrapper .header {
|
||||
color: ${widgetTitle};
|
||||
}`);
|
||||
}
|
||||
|
||||
// Title Inactive
|
||||
const tabInactiveBackground = theme.getColor(TAB_INACTIVE_BACKGROUND);
|
||||
const tabInactiveForeground = theme.getColor(TAB_INACTIVE_FOREGROUND);
|
||||
if (tabInactiveBackground || tabInactiveForeground) {
|
||||
collector.addRule(`
|
||||
panel.dashboard-panel > .tabbedPanel.horizontal > .title .tabList .tab .tabLabel {
|
||||
color: ${tabInactiveForeground};
|
||||
}
|
||||
panel.dashboard-panel > .tabbedPanel.horizontal > .title .tabList .tab-header {
|
||||
background-color: ${tabInactiveBackground};
|
||||
}
|
||||
`);
|
||||
// widget subtext
|
||||
const subText = theme.getColor(DASHBOARD_WIDGET_SUBTEXT);
|
||||
if (subText) {
|
||||
collector.addRule(`.subText {
|
||||
color: ${subText};
|
||||
}`);
|
||||
}
|
||||
|
||||
// Panel title background
|
||||
const panelTitleBackground = theme.getColor(EDITOR_GROUP_HEADER_TABS_BACKGROUND);
|
||||
if (panelTitleBackground) {
|
||||
collector.addRule(`
|
||||
panel.dashboard-panel > .tabbedPanel.horizontal > .title {
|
||||
background-color: ${panelTitleBackground};
|
||||
}
|
||||
`);
|
||||
}
|
||||
|
||||
// Panel title background
|
||||
const tabBorder = theme.getColor(TAB_BORDER);
|
||||
if (tabBorder) {
|
||||
collector.addRule(`
|
||||
panel.dashboard-panel > .tabbedPanel.horizontal > .title .tabList .tab-header {
|
||||
border-right-color: ${tabBorder};
|
||||
border-bottom-color: ${tabBorder};
|
||||
}
|
||||
`);
|
||||
}
|
||||
|
||||
// Styling with Outline color (e.g. high contrast theme)
|
||||
const outline = theme.getColor(activeContrastBorder);
|
||||
if (outline) {
|
||||
collector.addRule(`
|
||||
panel.dashboard-panel > .tabbedPanel.horizontal > .title {
|
||||
border-bottom-color: ${tabBorder};
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
|
||||
panel.dashboard-panel > .tabbedPanel.vertical > .title {
|
||||
border-right-color: ${tabBorder};
|
||||
border-right-width: 1px;
|
||||
border-right-style: solid;
|
||||
}
|
||||
`);
|
||||
}
|
||||
|
||||
const divider = theme.getColor(EDITOR_GROUP_BORDER);
|
||||
if (divider) {
|
||||
collector.addRule(`
|
||||
panel.dashboard-panel > .tabbedPanel.horizontal > .title .tabList .tab-header {
|
||||
border-right-width: 1px;
|
||||
border-right-style: solid;
|
||||
}
|
||||
`);
|
||||
}
|
||||
|
||||
const sideBorder = theme.getColor(DASHBOARD_BORDER);
|
||||
if (divider) {
|
||||
collector.addRule(`panel.dashboard-panel > .tabbedPanel.vertical > .title > .tabContainer {
|
||||
border-right-width: 1px;
|
||||
border-right-style: solid;
|
||||
border-right-color: ${sideBorder};
|
||||
// properties name
|
||||
const propertiesName = theme.getColor(DASHBOARD_PROPERTIES_NAME);
|
||||
if (propertiesName) {
|
||||
collector.addRule(`properties-widget .propertiesName {
|
||||
color: ${propertiesName}
|
||||
}`);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -17,6 +17,7 @@ import { GRID_CONTAINER, validateGridContainerContribution } from 'sql/workbench
|
||||
import { values } from 'vs/base/common/collections';
|
||||
import { IUserFriendlyIcon } from 'sql/workbench/contrib/dashboard/browser/core/dashboardWidget';
|
||||
import { isValidIcon, createCSSRuleForIcon } from 'sql/workbench/contrib/dashboard/browser/dashboardIconUtil';
|
||||
import { IDashboardTabGroup } from 'sql/workbench/services/dashboard/browser/common/interfaces';
|
||||
|
||||
export interface IDashboardTabContrib {
|
||||
id: string;
|
||||
@@ -237,3 +238,30 @@ ExtensionsRegistry.registerExtensionPoint<IDashboardTabContrib | IDashboardTabCo
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Predefined tab groups
|
||||
*/
|
||||
const PredefinedTabGroups: IDashboardTabGroup[] = [
|
||||
{
|
||||
id: 'administration',
|
||||
title: localize('administrationTabGroup', "Administration")
|
||||
}, {
|
||||
id: 'monitoring',
|
||||
title: localize('monitoringTabGroup', "Monitoring")
|
||||
}, {
|
||||
id: 'performance',
|
||||
title: localize('performanceTabGroup', "Performance")
|
||||
}, {
|
||||
id: 'security',
|
||||
title: localize('securityTabGroup', "Security")
|
||||
}, {
|
||||
id: 'troubleshooting',
|
||||
title: localize('troubleshootingTabGroup', "Troubleshooting")
|
||||
}, {
|
||||
id: 'settings',
|
||||
title: localize('settingsTabGroup', "Settings")
|
||||
}
|
||||
];
|
||||
|
||||
PredefinedTabGroups.forEach(tabGroup => registerTabGroup(tabGroup));
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2048 2048" width="16" height="16">
|
||||
<path d="M1792 569v1038l-832 417-832-417V569l832-417 832 417zM960 296L335 608l625 312 625-312-625-312zM256 1528l640 321v-817L256 711v817zm1408 0V711l-640 321v817l640-321z" />
|
||||
</svg>
|
||||
<svg id="a1d7ddca-c328-42f3-98f4-094c61aadb49" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18">
|
||||
<title>Icon-other-345</title>
|
||||
<polygon points="16.18 4.79 16.18 13.25 8.87 17.5 8.87 9.03 16.18 4.79" fill="#32bedd"/>
|
||||
<polygon points="16.18 4.79 8.87 9.04 1.55 4.78 8.87 0.53 16.18 4.79" fill="#9cebff"/>
|
||||
<polygon points="8.87 9.04 8.87 17.5 1.55 13.25 1.55 4.78 8.87 9.04" fill="#50e6ff"/>
|
||||
<polygon points="1.55 13.25 8.87 9.03 8.87 17.5 1.55 13.25" fill="#9cebff"/>
|
||||
<polygon points="16.18 13.25 8.87 9.03 8.87 17.5 16.18 13.25" fill="#50e6ff"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 271 B After Width: | Height: | Size: 593 B |
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M14,4.4v8.1l-6.5,3.3L1,12.6V4.4l6.5-3.3L14,4.4z M7.5,2.3L2.6,4.8l4.9,2.4l4.9-2.4L7.5,2.3z M2,11.9l5,2.5V8.1
|
||||
L2,5.6V11.9z M13,11.9V5.6L8,8.1v6.4L13,11.9z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 584 B |
@@ -1 +1,18 @@
|
||||
<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:none;}</style></defs><title>bv</title><path d="M8,1.289l7.352,7.359-.7.7L14,8.711V15H9V10H7v5H2V8.711l-.648.641-.7-.7ZM13,14V7.711l-5-5-5,5V14H6V9h4v5Z"/><rect class="cls-1" width="16" height="16"/></svg>
|
||||
<svg id="a7cb8cd6-2817-407b-b05e-da6a1a07986d" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18">
|
||||
<defs>
|
||||
<linearGradient id="f1d60ecc-f549-47b8-819a-b9b4b44e4c30" x1="9" y1="17.66" x2="9" y2="0.34" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#0078d4"/>
|
||||
<stop offset="0.17" stop-color="#1c84dc"/>
|
||||
<stop offset="0.38" stop-color="#3990e4"/>
|
||||
<stop offset="0.59" stop-color="#4d99ea"/>
|
||||
<stop offset="0.8" stop-color="#5a9eee"/>
|
||||
<stop offset="1" stop-color="#5ea0ef"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<title>Icon-general-17</title>
|
||||
<g>
|
||||
<path d="M17.8,8.29,9.41.5a.61.61,0,0,0-.82,0L.2,8.29A.62.62,0,0,0,.67,9.35H2.39a.3.3,0,0,1,.3.3v7.4a.61.61,0,0,0,.61.61H14.7a.61.61,0,0,0,.61-.61V9.65a.3.3,0,0,1,.3-.3h1.72A.62.62,0,0,0,17.8,8.29Z" fill="url(#f1d60ecc-f549-47b8-819a-b9b4b44e4c30)"/>
|
||||
<path id="b814d994-7069-4bdb-859e-2df17e42ed63" d="M7.07,12.4h3.86a.36.36,0,0,1,.32.38v4.88H6.75V12.78A.36.36,0,0,1,7.07,12.4Z" fill="#e6e6e6"/>
|
||||
<path d="M.67,9.35H1.2L8.59,2.49a.61.61,0,0,1,.82,0L16.8,9.35h.53a.62.62,0,0,0,.47-1.06L9.41.5a.61.61,0,0,0-.82,0L.2,8.29A.62.62,0,0,0,.67,9.35Z" fill="#005ba1"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 322 B After Width: | Height: | Size: 1.2 KiB |
@@ -1 +0,0 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#fff;}.cls-2{fill:none;}</style></defs><title>bv</title><path class="cls-1" d="M8,1.289l7.352,7.359-.7.7L14,8.711V15H9V10H7v5H2V8.711l-.648.641-.7-.7ZM13,14V7.711l-5-5-5,5V14H6V9h4v5Z"/><rect class="cls-2" width="16" height="16"/></svg>
|
||||
|
Before Width: | Height: | Size: 354 B |
@@ -35,7 +35,7 @@ export class DatabaseDashboardPage extends DashboardPage implements OnInit {
|
||||
background_color: colors.editorBackground,
|
||||
border: 'none',
|
||||
fontSize: '14px',
|
||||
padding: '5px 0 0 0',
|
||||
padding: '2px 0 0 0',
|
||||
provider: undefined,
|
||||
edition: undefined
|
||||
};
|
||||
|
||||
@@ -37,7 +37,7 @@ export class ServerDashboardPage extends DashboardPage implements OnInit {
|
||||
background_color: colors.editorBackground,
|
||||
border: 'none',
|
||||
fontSize: '14px',
|
||||
padding: '5px 0 0 0',
|
||||
padding: '2px 0 0 0',
|
||||
provider: undefined,
|
||||
edition: undefined
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* 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!./insightsWidget';
|
||||
|
||||
import {
|
||||
Component, Inject, forwardRef, AfterContentInit,
|
||||
@@ -46,7 +47,7 @@ interface IStorageResult {
|
||||
selector: 'insights-widget',
|
||||
template: `
|
||||
<div *ngIf="error" style="text-align: center; padding-top: 20px">{{error}}</div>
|
||||
<div *ngIf="lastUpdated" style="font-style: italic; font-size: 80%; margin-left: 5px">{{lastUpdated}}</div>
|
||||
<div *ngIf="lastUpdated" class="insights-widget-last-updated subText">{{lastUpdated}}</div>
|
||||
<div *ngIf="autoRefreshStatus" style="font-style: italic; font-size: 80%; margin-left: 5px">{{autoRefreshStatus}}</div>
|
||||
<div style="margin: 10px; width: calc(100% - 20px); height: calc(100% - 20px)">
|
||||
<ng-template *ngIf="!_loading" component-host></ng-template>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.insights-widget-last-updated {
|
||||
font-size: 10px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
@@ -11,8 +11,8 @@
|
||||
<span #child style="white-space : nowrap; width: fit-content">
|
||||
<ng-template ngFor let-item [ngForOf]="properties">
|
||||
<span style="margin-left: 10px; display: inline-block;">
|
||||
<div style="font-size: 11px;">{{item.displayName}}</div>
|
||||
<div>{{item.value}}</div>
|
||||
<div class="propertiesName" style="font-size: 11px;">{{item.displayName}}</div>
|
||||
<div class="propertiesValue">{{item.value}}</div>
|
||||
</span>
|
||||
</ng-template>
|
||||
</span>
|
||||
|
||||
@@ -13,6 +13,7 @@ import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { PANEL_BORDER } from 'vs/workbench/common/theme';
|
||||
|
||||
import { EditDataInput } from 'sql/workbench/browser/editData/editDataInput';
|
||||
|
||||
@@ -279,6 +280,7 @@ export class EditDataEditor extends BaseEditor {
|
||||
} else {
|
||||
this._resultsEditorContainer = DOM.append(parentElement, input.results.container);
|
||||
}
|
||||
this.updateStyles();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -297,6 +299,14 @@ export class EditDataEditor extends BaseEditor {
|
||||
this._sash.show();
|
||||
}
|
||||
|
||||
|
||||
updateStyles() {
|
||||
if (this._resultsEditorContainer) {
|
||||
this._resultsEditorContainer.style.borderTopColor = this.getColor(PANEL_BORDER);
|
||||
}
|
||||
super.updateStyles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the HTML for the SQL editor. Creates new HTML every time.
|
||||
*/
|
||||
@@ -619,12 +629,26 @@ export class EditDataEditor extends BaseEditor {
|
||||
} else {
|
||||
this._sash.hide();
|
||||
}
|
||||
this.updateSashVisibility();
|
||||
}
|
||||
|
||||
this._updateTaskbar(newInput);
|
||||
return this._setNewInput(newInput, options);
|
||||
}
|
||||
|
||||
private updateSashVisibility(): void {
|
||||
// change the visibility of the sash.
|
||||
if (this._resultsEditorContainer) {
|
||||
if (this.queryPaneEnabled()) {
|
||||
this._resultsEditorContainer.style.borderTopStyle = 'solid';
|
||||
this._resultsEditorContainer.style.borderTopWidth = '1px';
|
||||
} else {
|
||||
this._resultsEditorContainer.style.borderTopStyle = '';
|
||||
this._resultsEditorContainer.style.borderTopWidth = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _updateQueryEditorVisible(currentEditorIsVisible: boolean): void {
|
||||
if (this._queryEditorVisible) {
|
||||
let visible = currentEditorIsVisible;
|
||||
@@ -670,9 +694,11 @@ export class EditDataEditor extends BaseEditor {
|
||||
|
||||
public toggleQueryPane(): void {
|
||||
this.editDataInput.queryPaneEnabled = !this.queryPaneEnabled();
|
||||
this.updateSashVisibility();
|
||||
if (this.queryPaneEnabled()) {
|
||||
this._showQueryEditor();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
this._hideQueryEditor();
|
||||
}
|
||||
this._doLayout(false);
|
||||
|
||||
@@ -98,8 +98,9 @@ export class EditDataGridPanel extends GridParentComponent {
|
||||
@ILogService protected logService: ILogService
|
||||
) {
|
||||
super(contextMenuService, keybindingService, contextKeyService, configurationService, clipboardService, queryEditorService, logService);
|
||||
this.nativeElement = document.createElement('editdatagridpanel');
|
||||
this.nativeElement.className = 'slickgridContainer';
|
||||
this.nativeElement = document.createElement('div');
|
||||
this.nativeElement.className = 'editDataGridPanel';
|
||||
this.nativeElement.classList.add('slickgridContainer');
|
||||
this.dataService = dataService;
|
||||
this.actionProvider = this.instantiationService.createInstance(EditDataGridActionProvider, this.dataService, this.onGridSelectAll(), this.onDeleteRow(), this.onRevertRow());
|
||||
onRestoreViewState(() => this.restoreViewState());
|
||||
|
||||
@@ -24,7 +24,6 @@ import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
export class EditDataResultsEditor extends BaseEditor {
|
||||
|
||||
public static ID: string = 'workbench.editor.editDataResultsEditor';
|
||||
public static AngularSelectorString: string = 'slickgrid-container.slickgridContainer';
|
||||
protected _input: EditDataResultsInput;
|
||||
protected _rawOptions: BareResultsGridInfo;
|
||||
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.editdatagridpanel * {
|
||||
box-sizing: border-box;
|
||||
.editDataGridPanel.slickgridContainer {
|
||||
height: 447px;
|
||||
width: 632px;
|
||||
}
|
||||
|
||||
|
||||
#workbench\.editor\.editDataEditor .monaco-toolbar .monaco-select-box {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
|
||||
@@ -74,7 +74,6 @@ export function getBareResultsGridInfoStyles(info: BareResultsGridInfo): string
|
||||
export class QueryResultsEditor extends BaseEditor {
|
||||
|
||||
public static ID: string = 'workbench.editor.queryResultsEditor';
|
||||
public static AngularSelectorString: string = 'slickgrid-container.slickgridContainer';
|
||||
protected _rawOptions: BareResultsGridInfo;
|
||||
|
||||
private resultsView: QueryResultsView;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as nls from 'vs/nls';
|
||||
import { registerColor, editorBackground, contrastBorder, transparent, editorWidgetBackground, textLinkForeground, lighten, darken, focusBorder, activeContrastBorder, editorWidgetForeground, editorErrorForeground, editorWarningForeground, editorInfoForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { IColorTheme } from 'vs/platform/theme/common/themeService';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { Color, RGBA } from 'vs/base/common/color';
|
||||
|
||||
// < --- Workbench (not customizable) --- >
|
||||
|
||||
@@ -595,14 +595,50 @@ export const WINDOW_INACTIVE_BORDER = registerColor('window.inactiveBorder', {
|
||||
// {{SQL CARBON EDIT}}
|
||||
// < --- Dashboard --- >
|
||||
|
||||
export const DASHBOARD_TAB_ACTIVE_BACKGROUND = registerColor('dashboard.tabActiveBackground', {
|
||||
export const VERTICAL_TAB_ACTIVE_BACKGROUND = registerColor('tab.verticalTabActiveBackground', {
|
||||
dark: '#444444',
|
||||
light: '#e1f0fe',
|
||||
hc: TAB_ACTIVE_BACKGROUND
|
||||
}, nls.localize('dashboardTabActiveBackground', "Active tab background color for dashboard navigation"));
|
||||
}, nls.localize('verticalTabActiveBackground', "Active tab background color for vertical tabs"));
|
||||
|
||||
export const DASHBOARD_BORDER = registerColor('dashboard.border', {
|
||||
dark: '#8A8886',
|
||||
light: '#DDDDDD',
|
||||
hc: contrastBorder
|
||||
}, nls.localize('dashboardBorder', "Color for borders in dashboard"));
|
||||
|
||||
export const TAB_LABEL = registerColor('tab.tabLabel', {
|
||||
light: '#000000',
|
||||
dark: 'FFFFFF',
|
||||
hc: 'FFFFFF'
|
||||
}, nls.localize('tabLabel', "Color of tab label"));
|
||||
|
||||
export const TAB_GROUP_HEADER = registerColor('tab.tabGroupHeader', {
|
||||
light: '#dddddd',
|
||||
dark: '#dddddd',
|
||||
hc: '#FFFFFF'
|
||||
}, nls.localize('tabGroupHeader', "Color of tab group header"));
|
||||
|
||||
export const DASHBOARD_WIDGET_TITLE = registerColor('dashboardWidget.title', {
|
||||
light: '#323130',
|
||||
dark: '#FFFFFF',
|
||||
hc: '#FFFFFF'
|
||||
}, nls.localize('dashboardWidget', 'Color of dashboard widget title'));
|
||||
|
||||
export const DASHBOARD_WIDGET_SUBTEXT = registerColor('dashboardWidget.subText', {
|
||||
light: '#484644',
|
||||
dark: '#8A8886',
|
||||
hc: '#FFFFFF'
|
||||
}, nls.localize('dashboardWidgetSubtext', "Color for dashboard widget subtext"));
|
||||
|
||||
export const DASHBOARD_PROPERTIES_NAME = registerColor('dashboardWidget.propertiesName', {
|
||||
light: '#161616',
|
||||
dark: '#8A8886',
|
||||
hc: '#FFFFFF'
|
||||
}, nls.localize('dashboardWidgetPropertiesName', "Color for dashboard properties widget names"));
|
||||
|
||||
export const TOOLBAR_OVERFLOW_SHADOW = registerColor('toolbar.overflowShadow', {
|
||||
light: new Color(new RGBA(0, 0, 0, .132)),
|
||||
dark: new Color(new RGBA(0, 0, 0, 0.25)),
|
||||
hc: null
|
||||
}, nls.localize('toolbarOverflowShadow', "Toolbar overflow shadow color"));
|
||||
|
||||