Compare commits

..

2 Commits

Author SHA1 Message Date
Steve Faulkner
23599741d7 Fix strict mode 2020-09-10 18:39:52 -05:00
Steve Faulkner
d494278488 Refactor MemoryTracker to use SWR 2020-09-10 16:34:32 -05:00
57 changed files with 362 additions and 572 deletions

View File

@@ -4,4 +4,3 @@ PORTAL_RUNNER_PASSWORD=
PORTAL_RUNNER_SUBSCRIPTION=
PORTAL_RUNNER_RESOURCE_GROUP=
PORTAL_RUNNER_DATABASE_ACCOUNT=
PORTAL_RUNNER_CONNECTION_STRING=

View File

@@ -196,26 +196,6 @@ jobs:
shell: bash
env:
NODE_TLS_REJECT_UNAUTHORIZED: 0
endtoendpuppeteer:
name: "End to end puppeteer tests"
needs: [lint, format, compile, unittest]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js 12.x
uses: actions/setup-node@v1
with:
node-version: 12.x
- name: End to End Puppeteer Tests
run: |
npm ci
npm start &
npm run wait-for-server
npm run test:e2e
shell: bash
env:
NODE_TLS_REJECT_UNAUTHORIZED: 0
PORTAL_RUNNER_CONNECTION_STRING: ${{ secrets.CONNECTION_STRING_SQL }}
nuget:
name: Publish Nuget
if: github.ref == 'refs/heads/master' || contains(github.ref, 'hotfix/') || contains(github.ref, 'release/')

View File

@@ -3,8 +3,7 @@ const isCI = require("is-ci");
module.exports = {
launch: {
headless: isCI,
slowMo: 50,
defaultViewport: null,
ignoreHTTPSErrors: true
slowMo: isCI ? null : 20,
defaultViewport: null
}
};

View File

@@ -54,7 +54,7 @@
@SelectionColor: #3074B0;
@FocusColor: #605e5c;
@FocusColor: #00bcf2;
/******************************************************************************
METRICS

View File

@@ -1646,7 +1646,7 @@ p {
}
.contextual-pane .collid {
border: 1px solid #605e5c;
border: 1px solid #bbbbbb;
font-size: 10px;
padding: 5px 10px;
color: #000;
@@ -2423,6 +2423,22 @@ a:link {
display: none;
}
::-webkit-input-placeholder {
color: #969696;
}
::-moz-placeholder {
color: #969696;
}
:-ms-input-placeholder {
color: #969696;
}
:-moz-placeholder {
color: #969696;
}
::-ms-expand {
color: #969696;
}
@@ -3005,8 +3021,4 @@ settings-pane {
.warningErrorContent a {
color: @AccentMediumHigh
}
.infoBoxContent a {
color: @AccentMediumHigh
}
}

246
package-lock.json generated
View File

@@ -3490,9 +3490,9 @@
}
},
"@fluentui/date-time-utilities": {
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/@fluentui/date-time-utilities/-/date-time-utilities-7.8.0.tgz",
"integrity": "sha512-qzlTp3t+PghebJsLK9JwZr91qBRZ/fOml8TQCIjdtsEn4mH6/ciCwir7Fj8iOEkwwTC0iKsEr1jfsITtJKWSmA==",
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@fluentui/date-time-utilities/-/date-time-utilities-7.7.0.tgz",
"integrity": "sha512-rgtGX5x1AeYUfilfkgP6ag+ZKx41BJcUs16k6iSxXxd/mt00DAPOGY8ODGikKFpjGKcUwjKfYBssyKkVHDucfA==",
"requires": {
"@uifabric/set-version": "^7.0.22",
"tslib": "^1.10.0"
@@ -3517,9 +3517,9 @@
}
},
"@fluentui/react-focus": {
"version": "7.16.0",
"resolved": "https://registry.npmjs.org/@fluentui/react-focus/-/react-focus-7.16.0.tgz",
"integrity": "sha512-TwB4Av7ID70ejisDIGkCZGKOxlquSazr6W+9Jv1JQAvsBLuj5XOspFJH4/Igjniw1LeO9QmAvFZeh/XRShiObw==",
"version": "7.15.0",
"resolved": "https://registry.npmjs.org/@fluentui/react-focus/-/react-focus-7.15.0.tgz",
"integrity": "sha512-xbxB0cbyEoUfQZ19pAqBeWCYJ/4IOu1FG4bhVjDimqSD7qKwJbLlJSDNwmHr05SWprdhmqJe23KOwsHMgyvnrw==",
"requires": {
"@fluentui/keyboard-key": "^0.2.11",
"@uifabric/merge-styles": "^7.18.0",
@@ -3685,12 +3685,6 @@
"integrity": "sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA==",
"dev": true
},
"@hapi/formula": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-2.0.0.tgz",
"integrity": "sha512-V87P8fv7PI0LH7LiVi8Lkf3x+KCO7pQozXRssAHNXXL9L1K+uyu4XypLXwxqVDKgyQai6qj3/KteNlrqDx4W5A==",
"dev": true
},
"@hapi/hoek": {
"version": "8.5.1",
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-8.5.1.tgz",
@@ -3709,12 +3703,6 @@
"@hapi/topo": "3.x.x"
}
},
"@hapi/pinpoint": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-2.0.0.tgz",
"integrity": "sha512-vzXR5MY7n4XeIvLpfl3HtE3coZYO4raKXW766R6DZw/6aLqR26iuZ109K7a0NtF2Db0jxqh7xz2AxkUwpUFybw==",
"dev": true
},
"@hapi/topo": {
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-3.1.6.tgz",
@@ -7628,16 +7616,6 @@
"@types/enzyme": "*"
}
},
"@types/expect-puppeteer": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/@types/expect-puppeteer/-/expect-puppeteer-4.4.3.tgz",
"integrity": "sha512-jWZOO9d8ST2vutV5yxZ1OYxxtYD0lOufIgOUlDjyTNBGo8um67shJs2NQDLVDG06wWrabpPPOUQlI8GSvsdKVQ==",
"dev": true,
"requires": {
"@types/jest": "*",
"@types/puppeteer": "*"
}
},
"@types/geojson": {
"version": "7946.0.7",
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz",
@@ -7713,33 +7691,6 @@
"integrity": "sha512-DC8xTuW/6TYgvEg3HEXS7cu9OijFqprVDXXiOcdOKZCU/5PJNLZU37VVvmZHdtMiGOa8wAA/We+JzbdxFzQTRQ==",
"dev": true
},
"@types/jest-environment-puppeteer": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/@types/jest-environment-puppeteer/-/jest-environment-puppeteer-4.3.2.tgz",
"integrity": "sha512-QVR49cGaQMOrWRN7CXlvtPMuVAxa3Z+W3APxhWoSQLG/lvz1y03ECPvS7Y9eK+hgfndK+39400rO6IifDJV9YA==",
"dev": true,
"requires": {
"@jest/environment": "^24",
"@jest/fake-timers": "^24",
"@jest/types": "^24",
"@types/puppeteer": "*",
"jest-mock": "^24"
},
"dependencies": {
"@jest/environment": {
"version": "24.9.0",
"resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz",
"integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==",
"dev": true,
"requires": {
"@jest/fake-timers": "^24.9.0",
"@jest/transform": "^24.9.0",
"@jest/types": "^24.9.0",
"jest-mock": "^24.9.0"
}
}
}
},
"@types/json-schema": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz",
@@ -7815,15 +7766,6 @@
"integrity": "sha512-3AQoUxQcQtLHsK25wtTWIoIpgYjH3vSDroZOUr7PpCHw/jLY1RB9z9E8dBT/OSmwStVgkRNvdh+ZHNiomRieaw==",
"dev": true
},
"@types/puppeteer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-3.0.1.tgz",
"integrity": "sha512-t03eNKCvWJXhQ8wkc5C6GYuSqMEdKLOX0GLMGtks25YZr38wKZlKTwGM/BoAPVtdysX7Bb9tdwrDS1+NrW3RRA==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/pvutils": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/@types/pvutils/-/pvutils-0.0.1.tgz",
@@ -8447,6 +8389,46 @@
}
}
},
"@uifabric/react-hooks": {
"version": "7.11.0",
"resolved": "https://registry.npmjs.org/@uifabric/react-hooks/-/react-hooks-7.11.0.tgz",
"integrity": "sha512-iU7c+JR+rY5kBTPmrF8F6iJBQw309MX/MvOx6ElhmNceBaa8BqDuqR9+TVfkH+Bxp37bmZnCaQF5w4+QWHZ81g==",
"requires": {
"@uifabric/set-version": "^7.0.22",
"@uifabric/utilities": "^7.31.0",
"tslib": "^1.10.0"
},
"dependencies": {
"@uifabric/merge-styles": {
"version": "7.18.0",
"resolved": "https://registry.npmjs.org/@uifabric/merge-styles/-/merge-styles-7.18.0.tgz",
"integrity": "sha512-805WIbN7lAJATXKxZjjRbIgN7raRMwWYWeDkJJ52PCPuCesOvbpdr0GkH8rC6GQ7EB0MB7YM2i6Fiye7SFewbw==",
"requires": {
"@uifabric/set-version": "^7.0.22",
"tslib": "^1.10.0"
}
},
"@uifabric/set-version": {
"version": "7.0.22",
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.22.tgz",
"integrity": "sha512-IG35UNJNxqI7NC2eYuobGTD+v4W0VHQcC3bYd5Na9EgoC9jVgguS8n6EXUtP/lC1vJEYEyPEZdVwhPxKw4F4Sw==",
"requires": {
"tslib": "^1.10.0"
}
},
"@uifabric/utilities": {
"version": "7.31.0",
"resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-7.31.0.tgz",
"integrity": "sha512-m4Yeyn4gyW7xS8LvOnCesokPModYS2YuE9GQmO++MDZ/vC5RRNlvlyktUZDuxCZ84cNCiXyTQ8nImBaPGnxHVQ==",
"requires": {
"@uifabric/merge-styles": "^7.18.0",
"@uifabric/set-version": "^7.0.22",
"prop-types": "^15.7.2",
"tslib": "^1.10.0"
}
}
}
},
"@uifabric/set-version": {
"version": "7.0.15",
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.15.tgz",
@@ -8947,9 +8929,9 @@
}
},
"acorn-jsx": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
"integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz",
"integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==",
"dev": true
},
"acorn-walk": {
@@ -9334,13 +9316,6 @@
"integrity": "sha512-yG89F0j9B4B0MKIcFyWWxnpZPLaNTjCj4tkE3fjbAoo0qmpGw0PYYqSbX/4ebnd9Icn8ZgK4K1fvDyEtW1JYtQ==",
"requires": {
"pvutils": "^1.0.17"
},
"dependencies": {
"pvutils": {
"version": "1.0.17",
"resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.0.17.tgz",
"integrity": "sha512-wLHYUQxWaXVQvKnwIDWFVKDJku9XDCvyhhxoq8dc5MFdIlRenyPI9eSfEtcvgHgD7FlvCyGAlWgOzRnZD99GZQ=="
}
}
},
"assert": {
@@ -15066,6 +15041,12 @@
"pinkie-promise": "^2.0.0"
}
},
"fsevents": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
"integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
"optional": true
},
"get-caller-file": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
@@ -15114,6 +15095,7 @@
"@types/graceful-fs": "^4.1.2",
"anymatch": "^3.0.3",
"fb-watchman": "^2.0.0",
"fsevents": "^2.1.2",
"graceful-fs": "^4.2.4",
"jest-serializer": "^25.5.0",
"jest-util": "^25.5.0",
@@ -17675,19 +17657,6 @@
"requires": {
"has-flag": "^4.0.0"
}
},
"wait-on": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/wait-on/-/wait-on-3.3.0.tgz",
"integrity": "sha512-97dEuUapx4+Y12aknWZn7D25kkjMk16PbWoYzpSdA8bYpVfS6hpl2a2pOWZ3c+Tyt3/i4/pglyZctG3J4V1hWQ==",
"dev": true,
"requires": {
"@hapi/joi": "^15.0.3",
"core-js": "^2.6.5",
"minimist": "^1.2.0",
"request": "^2.88.0",
"rx": "^4.1.0"
}
}
}
},
@@ -22316,16 +22285,6 @@
"tslib": "^1.10.0"
}
},
"@uifabric/react-hooks": {
"version": "7.12.0",
"resolved": "https://registry.npmjs.org/@uifabric/react-hooks/-/react-hooks-7.12.0.tgz",
"integrity": "sha512-vPrg7NVtjjZlDS33tDUiyJSov8PNHBBX8w+EN9eatxP0g6dDkvGv8uWd+9Xpxrliuzi7ad7vlmUMOQffYJntMg==",
"requires": {
"@uifabric/set-version": "^7.0.22",
"@uifabric/utilities": "^7.31.0",
"tslib": "^1.10.0"
}
},
"@uifabric/set-version": {
"version": "7.0.22",
"resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.22.tgz",
@@ -23441,6 +23400,11 @@
"tslib": "^1.10.0"
}
},
"pvutils": {
"version": "1.0.17",
"resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.0.17.tgz",
"integrity": "sha512-wLHYUQxWaXVQvKnwIDWFVKDJku9XDCvyhhxoq8dc5MFdIlRenyPI9eSfEtcvgHgD7FlvCyGAlWgOzRnZD99GZQ=="
},
"q": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
@@ -23552,9 +23516,9 @@
}
},
"react": {
"version": "16.9.0",
"resolved": "https://registry.npmjs.org/react/-/react-16.9.0.tgz",
"integrity": "sha512-+7LQnFBwkiw+BobzOF6N//BdoNw0ouwmSJTEm9cglOOmsg/TMiFHZLe2sEoN5M7LgJTj9oHH0gxklfnQe66S1w==",
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz",
"integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==",
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
@@ -25791,6 +25755,23 @@
"resolved": "https://registry.npmjs.org/svgpath/-/svgpath-2.2.3.tgz",
"integrity": "sha512-xA0glXYpJ9SYT4JeMp3c0psbqdZsG1c0ywGvdJUPY2FKEgwJV7NgkeYuuQiOxMp+XsK9nCqjm3KDw0LkM1YLXw=="
},
"swr": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/swr/-/swr-0.3.2.tgz",
"integrity": "sha512-Bs5Bihq1hQ66O5bdKaL47iZ2nlAaBsd8tTLRLkw9stZeuBEfH7zSuQI95S2TpchL0ybsMq3isWwuso2uPvCfHA==",
"dev": true,
"requires": {
"fast-deep-equal": "2.0.1"
},
"dependencies": {
"fast-deep-equal": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
"dev": true
}
}
},
"symbol-observable": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
@@ -26937,65 +26918,16 @@
}
},
"wait-on": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/wait-on/-/wait-on-4.0.2.tgz",
"integrity": "sha512-Qpmgm3Hw/sXm7xK68FBsYy5r+Uid94/QymwnEjn9GTpfiWTUVYm0bccivVwY/BXGYO2r+5Cd8S/DzrRZqHK/9w==",
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/wait-on/-/wait-on-3.3.0.tgz",
"integrity": "sha512-97dEuUapx4+Y12aknWZn7D25kkjMk16PbWoYzpSdA8bYpVfS6hpl2a2pOWZ3c+Tyt3/i4/pglyZctG3J4V1hWQ==",
"dev": true,
"requires": {
"@hapi/joi": "^17.1.1",
"lodash": "^4.17.15",
"minimist": "^1.2.5",
"request": "^2.88.2",
"request-promise-native": "^1.0.8",
"rxjs": "^6.5.5"
},
"dependencies": {
"@hapi/address": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/@hapi/address/-/address-4.1.0.tgz",
"integrity": "sha512-SkszZf13HVgGmChdHo/PxchnSaCJ6cetVqLzyciudzZRT0jcOouIF/Q93mgjw8cce+D+4F4C1Z/WrfFN+O3VHQ==",
"dev": true,
"requires": {
"@hapi/hoek": "^9.0.0"
}
},
"@hapi/hoek": {
"version": "9.0.4",
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.0.4.tgz",
"integrity": "sha512-EwaJS7RjoXUZ2cXXKZZxZqieGtc7RbvQhUy8FwDoMQtxWVi14tFjeFCYPZAM1mBCpOpiBpyaZbb9NeHc7eGKgw==",
"dev": true
},
"@hapi/joi": {
"version": "17.1.1",
"resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-17.1.1.tgz",
"integrity": "sha512-p4DKeZAoeZW4g3u7ZeRo+vCDuSDgSvtsB/NpfjXEHTUjSeINAi/RrVOWiVQ1isaoLzMvFEhe8n5065mQq1AdQg==",
"dev": true,
"requires": {
"@hapi/address": "^4.0.1",
"@hapi/formula": "^2.0.0",
"@hapi/hoek": "^9.0.0",
"@hapi/pinpoint": "^2.0.0",
"@hapi/topo": "^5.0.0"
}
},
"@hapi/topo": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.0.0.tgz",
"integrity": "sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw==",
"dev": true,
"requires": {
"@hapi/hoek": "^9.0.0"
}
},
"rxjs": {
"version": "6.6.2",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz",
"integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==",
"dev": true,
"requires": {
"tslib": "^1.9.0"
}
}
"@hapi/joi": "^15.0.3",
"core-js": "^2.6.5",
"minimist": "^1.2.0",
"request": "^2.88.0",
"rx": "^4.1.0"
}
},
"wait-port": {

View File

@@ -72,7 +72,7 @@
"promise-polyfill": "8.1.0",
"promise.prototype.finally": "3.1.0",
"q": "1.5.1",
"react": "16.9.0",
"react": "16.13.1",
"react-animate-height": "2.0.8",
"react-dnd": "9.4.0",
"react-dnd-html5-backend": "9.4.0",
@@ -102,15 +102,12 @@
"@types/d3": "4.13.2",
"@types/enzyme": "3.10.3",
"@types/enzyme-adapter-react-16": "1.0.5",
"@types/expect-puppeteer": "4.4.3",
"@types/hasher": "0.0.31",
"@types/jest": "23.3.10",
"@types/jest-environment-puppeteer": "4.3.2",
"@types/memoize-one": "4.1.1",
"@types/node": "12.11.1",
"@types/promise.prototype.finally": "2.0.3",
"@types/prop-types": "15.5.8",
"@types/puppeteer": "3.0.1",
"@types/q": "1.5.1",
"@types/react": "16.8.25",
"@types/react-dom": "16.0.7",
@@ -163,13 +160,13 @@
"rimraf": "3.0.0",
"sinon": "3.2.1",
"style-loader": "0.23.0",
"swr": "0.3.2",
"terser-webpack-plugin": "3.0.5",
"ts-loader": "6.2.2",
"tslint": "5.11.0",
"tslint-microsoft-contrib": "6.0.0",
"typescript": "4.0.2",
"url-loader": "1.1.1",
"wait-on": "4.0.2",
"webpack": "4.43.0",
"webpack-bundle-analyzer": "3.6.1",
"webpack-cli": "3.3.10",
@@ -188,7 +185,6 @@
"test": "rimraf coverage && jest",
"test:e2e": "jest -c ./jest.config.e2e.js --detectOpenHandles",
"watch": "npm run start",
"wait-for-server": "wait-on -t 240000 -i 5000 -v https-get://0.0.0.0:1234/",
"build:ase": "gulp build:ase",
"compile": "tsc",
"compile:contracts": "tsc -p ./tsconfig.contracts.json",

View File

@@ -122,7 +122,6 @@ export class Features {
public static readonly enableTtl = "enablettl";
public static readonly enableNotebooks = "enablenotebooks";
public static readonly enableGalleryPublish = "enablegallerypublish";
public static readonly enableQueryTabV2 = "enablequerytabv2";
public static readonly enableCodeOfConduct = "enablecodeofconduct";
public static readonly enableLinkInjection = "enablelinkinjection";
public static readonly enableSpark = "enablespark";

View File

@@ -6,23 +6,26 @@ import { ContainerRequest } from "@azure/cosmos/dist-esm/client/Container/Contai
import { DatabaseRequest } from "@azure/cosmos/dist-esm/client/Database/DatabaseRequest";
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
import { RequestOptions } from "@azure/cosmos/dist-esm";
import * as ARMTypes from "../../Utils/arm/generatedClients/2020-04-01/types";
import * as ARMTypes from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/types";
import { client } from "../CosmosClient";
import { createMongoCollectionWithProxy } from "../MongoProxyClient";
import { createUpdateSqlContainer, getSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
import {
createUpdateSqlContainer,
getSqlContainer
} from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/sqlResources";
import {
createUpdateCassandraTable,
getCassandraTable
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
} from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/cassandraResources";
import {
createUpdateMongoDBCollection,
getMongoDBCollection
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
} from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/mongoDBResources";
import {
createUpdateGremlinGraph,
getGremlinGraph
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
import { createUpdateTable, getTable } from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
} from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/gremlinResources";
import { createUpdateTable, getTable } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/tableResources";
import { logConsoleProgress, logConsoleError, logConsoleInfo } from "../../Utils/NotificationConsoleUtils";
import { logError } from "../Logger";
import { refreshCachedResources } from "../DataAccessUtilityBase";

View File

@@ -9,21 +9,24 @@ import {
MongoDBDatabaseCreateUpdateParameters,
SqlDatabaseCreateUpdateParameters,
CreateUpdateOptions
} from "../../Utils/arm/generatedClients/2020-04-01/types";
} from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/types";
import { client } from "../CosmosClient";
import { createUpdateSqlDatabase, getSqlDatabase } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
import {
createUpdateSqlDatabase,
getSqlDatabase
} from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/sqlResources";
import {
createUpdateCassandraKeyspace,
getCassandraKeyspace
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
} from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/cassandraResources";
import {
createUpdateMongoDBDatabase,
getMongoDBDatabase
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
} from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/mongoDBResources";
import {
createUpdateGremlinDatabase,
getGremlinDatabase
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
} from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/gremlinResources";
import { logConsoleProgress, logConsoleError, logConsoleInfo } from "../../Utils/NotificationConsoleUtils";
import { logError } from "../Logger";
import { refreshCachedOffers, refreshCachedResources } from "../DataAccessUtilityBase";

View File

@@ -1,10 +1,10 @@
import { AuthType } from "../../AuthType";
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
import { deleteSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
import { deleteCassandraTable } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
import { deleteMongoDBCollection } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
import { deleteGremlinGraph } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
import { deleteTable } from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
import { deleteSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/sqlResources";
import { deleteCassandraTable } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/cassandraResources";
import { deleteMongoDBCollection } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/mongoDBResources";
import { deleteGremlinGraph } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/gremlinResources";
import { deleteTable } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/tableResources";
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { logError } from "../Logger";
import { sendNotificationForError } from "./sendNotificationForError";

View File

@@ -1,9 +1,9 @@
import { AuthType } from "../../AuthType";
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
import { deleteSqlDatabase } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
import { deleteCassandraKeyspace } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
import { deleteMongoDBDatabase } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
import { deleteGremlinDatabase } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
import { deleteSqlDatabase } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/sqlResources";
import { deleteCassandraKeyspace } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/cassandraResources";
import { deleteMongoDBDatabase } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/mongoDBResources";
import { deleteGremlinDatabase } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/gremlinResources";
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { userContext } from "../../UserContext";
import { client } from "../CosmosClient";

View File

@@ -2,11 +2,11 @@ import * as DataModels from "../../Contracts/DataModels";
import { AuthType } from "../../AuthType";
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
import { client } from "../CosmosClient";
import { listSqlContainers } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
import { listCassandraTables } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
import { listMongoDBCollections } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
import { listGremlinGraphs } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
import { listTables } from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
import { listSqlContainers } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/sqlResources";
import { listCassandraTables } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/cassandraResources";
import { listMongoDBCollections } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/mongoDBResources";
import { listGremlinGraphs } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/gremlinResources";
import { listTables } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/tableResources";
import { logConsoleProgress, logConsoleError } from "../../Utils/NotificationConsoleUtils";
import { logError } from "../Logger";
import { sendNotificationForError } from "./sendNotificationForError";

View File

@@ -2,10 +2,10 @@ import * as DataModels from "../../Contracts/DataModels";
import { AuthType } from "../../AuthType";
import { DefaultAccountExperienceType } from "../../DefaultAccountExperienceType";
import { client } from "../CosmosClient";
import { listSqlDatabases } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
import { listCassandraKeyspaces } from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
import { listMongoDBDatabases } from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
import { listGremlinDatabases } from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
import { listSqlDatabases } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/sqlResources";
import { listCassandraKeyspaces } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/cassandraResources";
import { listMongoDBDatabases } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/mongoDBResources";
import { listGremlinDatabases } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/gremlinResources";
import { logConsoleProgress, logConsoleError } from "../../Utils/NotificationConsoleUtils";
import { logError } from "../Logger";
import { sendNotificationForError } from "./sendNotificationForError";

View File

@@ -6,23 +6,26 @@ import {
ExtendedResourceProperties,
SqlContainerCreateUpdateParameters,
SqlContainerResource
} from "../../Utils/arm/generatedClients/2020-04-01/types";
} from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/types";
import { RequestOptions } from "@azure/cosmos/dist-esm";
import { client } from "../CosmosClient";
import { createUpdateSqlContainer, getSqlContainer } from "../../Utils/arm/generatedClients/2020-04-01/sqlResources";
import {
createUpdateSqlContainer,
getSqlContainer
} from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/sqlResources";
import {
createUpdateCassandraTable,
getCassandraTable
} from "../../Utils/arm/generatedClients/2020-04-01/cassandraResources";
} from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/cassandraResources";
import {
createUpdateMongoDBCollection,
getMongoDBCollection
} from "../../Utils/arm/generatedClients/2020-04-01/mongoDBResources";
} from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/mongoDBResources";
import {
createUpdateGremlinGraph,
getGremlinGraph
} from "../../Utils/arm/generatedClients/2020-04-01/gremlinResources";
import { createUpdateTable, getTable } from "../../Utils/arm/generatedClients/2020-04-01/tableResources";
} from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/gremlinResources";
import { createUpdateTable, getTable } from "../../Utils/arm/generatedClients/2020-04-01-cosmos-db/tableResources";
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { logError } from "../Logger";
import { refreshCachedResources } from "../DataAccessUtilityBase";

View File

@@ -709,11 +709,6 @@ export interface SparkPool extends ArmResource {
properties: SparkPoolProperties;
}
export interface MemoryUsageInfo {
freeKB: number;
totalKB: number;
}
export interface resourceTokenConnectionStringProperties {
accountEndpoint: string;
collectionId: string;

View File

@@ -353,8 +353,7 @@ export enum CollectionTabKind {
NotebookV2 = 15,
SparkMasterTab = 16,
Gallery = 17,
NotebookViewer = 18,
QueryV2 = 19
NotebookViewer = 18
}
export enum TerminalKind {

View File

@@ -35,7 +35,6 @@ ko.components.register("trigger-tab", new TabComponents.TriggerTab());
ko.components.register("user-defined-function-tab", new TabComponents.UserDefinedFunctionTab());
ko.components.register("settings-tab", new TabComponents.SettingsTab());
ko.components.register("query-tab", new TabComponents.QueryTab());
ko.components.register("query-tab-v2", new TabComponents.QueryTabV2());
ko.components.register("tables-query-tab", new TabComponents.QueryTablesTab());
ko.components.register("graph-tab", new TabComponents.GraphTab());
ko.components.register("mongo-shell-tab", new TabComponents.MongoShellTab());

View File

@@ -1,20 +0,0 @@
import * as React from "react";
import QueryTabV2 from "../../Tabs/QueryTabV2";
export interface QueryComponentProps {
queryTab: QueryTabV2
}
interface QueryComponentState {
}
export class QueryComponent extends React.Component<QueryComponentProps, QueryComponentState> {
public render() : JSX.Element {
return (
<h1>
Query tab v2 is here
</h1>
)
}
}

View File

@@ -1,21 +0,0 @@
import ko from "knockout";
import * as React from "react";
import { ReactAdapter } from "../../../Bindings/ReactBindingHandler";
import { QueryComponent, QueryComponentProps } from "./QueryComponent";
export class QueryComponentAdapter implements ReactAdapter {
public parameters: ko.Observable<number>;
constructor(private props: QueryComponentProps) {
this.parameters = ko.observable<number>(Date.now());
console.log("adapter intiialized")
}
public renderComponent(): JSX.Element {
return <QueryComponent {...this.props} />;
}
public triggerRender(): void {
window.requestAnimationFrame(() => this.parameters(Date.now()));
}
}

View File

@@ -209,7 +209,6 @@ export default class Explorer {
// features
public isGalleryPublishEnabled: ko.Computed<boolean>;
public isQueryTabV2Enabled: ko.Computed<boolean>;
public isCodeOfConductEnabled: ko.Computed<boolean>;
public isLinkInjectionEnabled: ko.Computed<boolean>;
public isGitHubPaneEnabled: ko.Observable<boolean>;
@@ -244,7 +243,6 @@ export default class Explorer {
public arcadiaWorkspaces: ko.ObservableArray<ArcadiaWorkspaceItem>;
public hasStorageAnalyticsAfecFeature: ko.Observable<boolean>;
public isSynapseLinkUpdating: ko.Observable<boolean>;
public memoryUsageInfo: ko.Observable<DataModels.MemoryUsageInfo>;
public notebookManager?: any; // This is dynamically loaded
private _panes: ContextualPaneBase[] = [];
@@ -375,7 +373,6 @@ export default class Explorer {
);
}
});
this.memoryUsageInfo = ko.observable<DataModels.MemoryUsageInfo>();
this.notificationsClient = options.notificationsClient;
this.isEmulator = options.isEmulator;
@@ -415,9 +412,6 @@ export default class Explorer {
this.isGalleryPublishEnabled = ko.computed<boolean>(() =>
this.isFeatureEnabled(Constants.Features.enableGalleryPublish)
);
this.isQueryTabV2Enabled = ko.computed<boolean>(() =>
this.isFeatureEnabled(Constants.Features.enableQueryTabV2)
);
this.isCodeOfConductEnabled = ko.computed<boolean>(() =>
this.isFeatureEnabled(Constants.Features.enableCodeOfConduct)
);
@@ -1897,9 +1891,6 @@ export default class Explorer {
}
public findSelectedDatabase(): ViewModels.Database {
if (!this.selectedNode()) {
return null;
}
if (this.selectedNode().nodeKind === "Database") {
return _.find(this.databases(), (database: ViewModels.Database) => database.rid === this.selectedNode().rid);
}

View File

@@ -82,9 +82,7 @@ export class CommandBarComponentAdapter implements ReactAdapter {
uiFabricControlButtons.forEach((btn: ICommandBarItemProps) => (btn.iconOnly = true));
if (this.isNotebookTabActive()) {
uiFabricControlButtons.unshift(
CommandBarUtil.createMemoryTracker("memoryTracker", this.container.memoryUsageInfo)
);
uiFabricControlButtons.unshift(CommandBarUtil.createMemoryTracker("memoryTracker"));
}
return (

View File

@@ -1,16 +1,14 @@
import _ from "underscore";
import * as React from "react";
import { Observable } from "knockout";
import { ICommandBarItemProps } from "office-ui-fabric-react/lib/CommandBar";
import { Dropdown, IDropdownOption, IDropdownStyles } from "office-ui-fabric-react/lib/Dropdown";
import { IconType } from "office-ui-fabric-react/lib/Icon";
import { IComponentAsProps } from "office-ui-fabric-react/lib/Utilities";
import { StyleConstants } from "../../../Common/Constants";
import { ICommandBarItemProps } from "office-ui-fabric-react/lib/CommandBar";
import { Dropdown, IDropdownStyles, IDropdownOption } from "office-ui-fabric-react/lib/Dropdown";
import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent";
import * as React from "react";
import _ from "underscore";
import ChevronDownIcon from "../../../../images/Chevron_down.svg";
import { StyleConstants } from "../../../Common/Constants";
import { ArcadiaMenuPicker } from "../../Controls/Arcadia/ArcadiaMenuPicker";
import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent";
import { MemoryTrackerComponent } from "./MemoryTrackerComponent";
import { MemoryUsageInfo } from "../../../Contracts/DataModels";
/**
* Utilities for CommandBar
@@ -178,10 +176,10 @@ export class CommandBarUtil {
};
}
public static createMemoryTracker(key: string, memoryUsageInfo: Observable<MemoryUsageInfo>): ICommandBarItemProps {
public static createMemoryTracker(key: string): ICommandBarItemProps {
return {
key,
onRender: () => <MemoryTrackerComponent memoryUsageInfo={memoryUsageInfo} />
onRender: () => <MemoryTrackerComponent />
};
}
}

View File

@@ -1,50 +1,71 @@
import * as React from "react";
import { Observable, Subscription } from "knockout";
import { MemoryUsageInfo } from "../../../Contracts/DataModels";
import React, { FunctionComponent } from "react";
import useSWR from "swr";
import { ProgressIndicator } from "office-ui-fabric-react/lib/ProgressIndicator";
import { Spinner, SpinnerSize } from "office-ui-fabric-react/lib/Spinner";
import { Stack } from "office-ui-fabric-react/lib/Stack";
import { listConnectionInfo } from "../../../Utils/arm/generatedClients/2020-04-01-notebook/notebookWorkspaces";
import { NotebookWorkspaceConnectionInfoResult } from "../../../Utils/arm/generatedClients/2020-04-01-notebook/types";
import { userContext } from "../../../UserContext";
interface MemoryTrackerProps {
memoryUsageInfo: Observable<MemoryUsageInfo>;
export interface MemoryUsageInfo {
total: number;
free: number;
}
export class MemoryTrackerComponent extends React.Component<MemoryTrackerProps> {
private memoryUsageInfoSubscription: Subscription;
const kbInGB = 1048576;
public componentDidMount(): void {
this.memoryUsageInfoSubscription = this.props.memoryUsageInfo.subscribe(() => {
this.forceUpdate();
});
}
public componentWillUnmount(): void {
this.memoryUsageInfoSubscription && this.memoryUsageInfoSubscription.dispose();
}
public render(): JSX.Element {
const memoryUsageInfo: MemoryUsageInfo = this.props.memoryUsageInfo();
if (!memoryUsageInfo) {
return (
<Stack className="memoryTrackerContainer" horizontal>
<span>Memory</span>
<Spinner size={SpinnerSize.medium} />
</Stack>
);
const fetchMemoryInfo = async (_key: unknown, connectionInfo: NotebookWorkspaceConnectionInfoResult) => {
const response = await fetch(`${connectionInfo.notebookServerEndpoint}/api/metrics/memory`, {
method: "GET",
headers: {
Authorization: `Token ${connectionInfo.authToken}`,
"content-type": "application/json"
}
});
if (!response.ok) {
throw new Error(await response.text());
}
const memoryUsageInfo = (await response.json()) as MemoryUsageInfo;
return {
totalKB: memoryUsageInfo.total,
freeKB: memoryUsageInfo.free
};
};
const totalGB = memoryUsageInfo.totalKB / 1048576;
const usedGB = totalGB - memoryUsageInfo.freeKB / 1048576;
export const MemoryTrackerComponent: FunctionComponent = () => {
const { data: connectionInfo } = useSWR(
[
"notebooksConnectionInfo",
userContext.subscriptionId,
userContext.resourceGroup,
userContext.databaseAccount.name,
"default"
],
(_key, subscriptionId, resourceGroup, accountName, workspace) =>
listConnectionInfo(subscriptionId, resourceGroup, accountName, workspace)
);
const { data } = useSWR(connectionInfo ? ["memoryUsage", connectionInfo] : null, fetchMemoryInfo, {
refreshInterval: 2000
});
if (!data) {
return (
<Stack className="memoryTrackerContainer" horizontal>
<span>Memory</span>
<ProgressIndicator
className={usedGB / totalGB > 0.8 ? "lowMemory" : ""}
description={usedGB.toFixed(1) + " of " + totalGB.toFixed(1) + " GB"}
percentComplete={usedGB / totalGB}
/>
<Spinner size={SpinnerSize.medium} />
</Stack>
);
}
}
const totalGB = data.totalKB / kbInGB;
const usedGB = totalGB - data.freeKB / kbInGB;
return (
<Stack className="memoryTrackerContainer" horizontal>
<span>Memory</span>
<ProgressIndicator
className={usedGB / totalGB > 0.8 ? "lowMemory" : ""}
description={usedGB.toFixed(1) + " of " + totalGB.toFixed(1) + " GB"}
percentComplete={usedGB / totalGB}
/>
</Stack>
);
};

View File

@@ -2,89 +2,13 @@
* Notebook container related stuff
*/
import * as DataModels from "../../Contracts/DataModels";
import * as Constants from "../../Common/Constants";
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
import * as Logger from "../../Common/Logger";
export class NotebookContainerClient {
private reconnectingNotificationId: string;
private isResettingWorkspace: boolean;
constructor(
private notebookServerInfo: ko.Observable<DataModels.NotebookWorkspaceConnectionInfo>,
private onConnectionLost: () => void,
private onMemoryUsageInfoUpdate: (update: DataModels.MemoryUsageInfo) => void
) {
if (notebookServerInfo() && notebookServerInfo().notebookServerEndpoint) {
this.scheduleHeartbeat(Constants.Notebook.heartbeatDelayMs);
} else {
const subscription = notebookServerInfo.subscribe((newServerInfo: DataModels.NotebookWorkspaceConnectionInfo) => {
if (newServerInfo && newServerInfo.notebookServerEndpoint) {
this.scheduleHeartbeat(Constants.Notebook.heartbeatDelayMs);
}
subscription.dispose();
});
}
}
/**
* Heartbeat: each ping schedules another ping
*/
private scheduleHeartbeat(delayMs: number): void {
setTimeout(() => {
this.getMemoryUsage()
.then(memoryUsageInfo => this.onMemoryUsageInfoUpdate(memoryUsageInfo))
.finally(() => this.scheduleHeartbeat(Constants.Notebook.heartbeatDelayMs));
}, delayMs);
}
private async getMemoryUsage(): Promise<DataModels.MemoryUsageInfo> {
if (!this.notebookServerInfo() || !this.notebookServerInfo().notebookServerEndpoint) {
const error = "No server endpoint detected";
Logger.logError(error, "NotebookContainerClient/getMemoryUsage");
return Promise.reject(error);
}
if (this.isResettingWorkspace) {
return undefined;
}
const { notebookServerEndpoint, authToken } = this.getNotebookServerConfig();
try {
const response = await fetch(`${notebookServerEndpoint}/api/metrics/memory`, {
method: "GET",
headers: {
Authorization: authToken,
"content-type": "application/json"
}
});
if (response.ok) {
if (this.reconnectingNotificationId) {
NotificationConsoleUtils.clearInProgressMessageWithId(this.reconnectingNotificationId);
this.reconnectingNotificationId = "";
}
const memoryUsageInfo = await response.json();
if (memoryUsageInfo) {
return {
totalKB: memoryUsageInfo.total,
freeKB: memoryUsageInfo.free
};
}
}
return undefined;
} catch (error) {
Logger.logError(error, "NotebookContainerClient/getMemoryUsage");
if (!this.reconnectingNotificationId) {
this.reconnectingNotificationId = NotificationConsoleUtils.logConsoleMessage(
ConsoleDataType.InProgress,
"Connection lost with Notebook server. Attempting to reconnect..."
);
}
this.onConnectionLost();
return undefined;
}
}
constructor(private notebookServerInfo: ko.Observable<DataModels.NotebookWorkspaceConnectionInfo>) {}
public async resetWorkspace(): Promise<void> {
this.isResettingWorkspace = true;

View File

@@ -16,7 +16,6 @@ import { NotebookContentProvider } from "./NotebookComponent/NotebookContentProv
import { GitHubContentProvider } from "../../GitHub/GitHubContentProvider";
import { contents } from "rx-jupyter";
import { NotebookContainerClient } from "./NotebookContainerClient";
import { MemoryUsageInfo } from "../../Contracts/DataModels";
import { NotebookContentClient } from "./NotebookContentClient";
import { DialogProps } from "../Controls/DialogReactComponent/DialogComponent";
import { ResourceTreeAdapter } from "../Tree/ResourceTreeAdapter";
@@ -76,11 +75,7 @@ export default class NotebookManager {
contents.JupyterContentProvider
);
this.notebookClient = new NotebookContainerClient(
this.params.container.notebookServerInfo,
() => this.params.container.initNotebooks(this.params.container.databaseAccount()),
(update: MemoryUsageInfo) => this.params.container.memoryUsageInfo(update)
);
this.notebookClient = new NotebookContainerClient(this.params.container.notebookServerInfo);
this.notebookContentClient = new NotebookContentClient(
this.params.container.notebookServerInfo,

View File

@@ -1 +0,0 @@
<div style="height: 100%" data-bind="react:queryComponentAdapter"></div>

View File

@@ -1,17 +0,0 @@
import * as ViewModels from "../../Contracts/ViewModels";
import TabsBase from "./TabsBase";
import { QueryComponentAdapter } from "../Controls/Query/QueryComponentAdapter"
import { QueryComponentProps } from "../Controls/Query/QueryComponent";
export default class QueryTabV2 extends TabsBase {
public queryComponentAdapter: QueryComponentAdapter;
constructor(options: ViewModels.QueryTabOptions) {
super(options);
const props: QueryComponentProps = {
queryTab: this
};
this.queryComponentAdapter = new QueryComponentAdapter(props);
}
}

View File

@@ -17,7 +17,6 @@ import UserDefinedFunctionTabTemplate from "./UserDefinedFunctionTab.html";
import GalleryTabTemplate from "./GalleryTab.html";
import NotebookViewerTabTemplate from "./NotebookViewerTab.html";
import TabsManagerTemplate from "./TabsManager.html";
import QueryTabV2Template from "./QueryTabV2.html";
export class TabComponent {
constructor(data: any) {
@@ -124,15 +123,6 @@ export class QueryTab {
}
}
export class QueryTabV2 {
constructor() {
return {
viewModel: TabComponent,
template: QueryTabV2Template
};
}
}
export class QueryTablesTab {
constructor() {
return {

View File

@@ -141,11 +141,6 @@
<!-- ko if: $data.tabKind === 18 -->
<notebook-viewer-tab params="{data: $data}"></notebook-viewer-tab>
<!-- /ko -->
<!-- ko if: $data.tabKind === 19 -->
<query-tab-v2 params="{data: $data}"></query-tab-v2>
<!-- /ko -->
</div>
<!-- /ko -->
</div>

View File

@@ -42,8 +42,6 @@ import {
readOffers
} from "../../Common/DocumentClientUtilityBase";
import { userContext } from "../../UserContext";
import TabsBase from "../Tabs/TabsBase";
import QueryTabV2 from "../Tabs/QueryTabV2";
export default class Collection implements ViewModels.Collection {
public nodeKind: string;
@@ -731,9 +729,8 @@ export default class Collection implements ViewModels.Collection {
}
public onNewQueryClick(source: any, event: MouseEvent, queryText?: string) {
const queryTabType = this.container.isQueryTabV2Enabled ? ViewModels.CollectionTabKind.QueryV2 : ViewModels.CollectionTabKind.Query
const collection: ViewModels.Collection = source.collection || source;
const id = this.container.tabsManager.getTabs(queryTabType).length + 1;
const id = this.container.tabsManager.getTabs(ViewModels.CollectionTabKind.Query).length + 1;
const title = "Query " + id;
const startKey: number = TelemetryProcessor.traceStart(Action.Tab, {
databaseAccountName: this.container.databaseAccount().name,
@@ -744,8 +741,8 @@ export default class Collection implements ViewModels.Collection {
tabTitle: title
});
const queryTabProps : ViewModels.QueryTabOptions = {
tabKind: queryTabType,
const queryTab: QueryTab = new QueryTab({
tabKind: ViewModels.CollectionTabKind.Query,
title: title,
tabPath: "",
collection: this,
@@ -757,9 +754,7 @@ export default class Collection implements ViewModels.Collection {
partitionKey: collection.partitionKey,
onLoadStartKey: startKey,
onUpdateTabsButtons: this.container.onUpdateTabsButtons
}
const queryTab = this.container.isQueryTabV2Enabled ? new QueryTab(queryTabProps) : new QueryTabV2(queryTabProps)
});
this.container.tabsManager.activateNewTab(queryTab);
}

View File

@@ -0,0 +1,87 @@
/*
AUTOGENERATED FILE
Do not manually edit
Run "npm run generateARMClients" to regenerate
*/
import { armRequest } from "../../request";
import * as Types from "./types";
import { configContext } from "../../../../ConfigContext";
const apiVersion = "2020-04-01";
/* Gets the notebook workspace resources of an existing Cosmos DB account. */
export async function listByDatabaseAccount(
subscriptionId: string,
resourceGroupName: string,
accountName: string
): Promise<Types.NotebookWorkspaceListResult> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/notebookWorkspaces`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "GET", apiVersion });
}
/* Gets the notebook workspace for a Cosmos DB account. */
export async function get(
subscriptionId: string,
resourceGroupName: string,
accountName: string,
notebookWorkspaceName: string
): Promise<Types.NotebookWorkspace> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/notebookWorkspaces/${notebookWorkspaceName}`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "GET", apiVersion });
}
/* Creates the notebook workspace for a Cosmos DB account. */
export async function createOrUpdate(
subscriptionId: string,
resourceGroupName: string,
accountName: string,
notebookWorkspaceName: string,
body: Types.NotebookWorkspaceCreateUpdateParameters
): Promise<Types.NotebookWorkspace> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/notebookWorkspaces/${notebookWorkspaceName}`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "PUT", apiVersion, body });
}
/* Deletes the notebook workspace for a Cosmos DB account. */
export async function destroy(
subscriptionId: string,
resourceGroupName: string,
accountName: string,
notebookWorkspaceName: string
): Promise<void> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/notebookWorkspaces/${notebookWorkspaceName}`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "DELETE", apiVersion });
}
/* Retrieves the connection info for the notebook workspace */
export async function listConnectionInfo(
subscriptionId: string,
resourceGroupName: string,
accountName: string,
notebookWorkspaceName: string
): Promise<Types.NotebookWorkspaceConnectionInfoResult> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/notebookWorkspaces/${notebookWorkspaceName}/listConnectionInfo`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "POST", apiVersion });
}
/* Regenerates the auth token for the notebook workspace */
export async function regenerateAuthToken(
subscriptionId: string,
resourceGroupName: string,
accountName: string,
notebookWorkspaceName: string
): Promise<void> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/notebookWorkspaces/${notebookWorkspaceName}/regenerateAuthToken`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "POST", apiVersion });
}
/* Starts the notebook workspace */
export async function start(
subscriptionId: string,
resourceGroupName: string,
accountName: string,
notebookWorkspaceName: string
): Promise<void> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/notebookWorkspaces/${notebookWorkspaceName}/start`;
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "POST", apiVersion });
}

View File

@@ -0,0 +1,36 @@
/*
AUTOGENERATED FILE
Do not manually edit
Run "npm run generateARMClients" to regenerate
*/
/* Parameters to create a notebook workspace resource */
export type NotebookWorkspaceCreateUpdateParameters = unknown;
/* A list of notebook workspace resources */
export interface NotebookWorkspaceListResult {
/* Array of notebook workspace resources */
value?: NotebookWorkspace[];
}
/* A notebook workspace resource */
export type NotebookWorkspace = unknown & {
/* Resource properties. */
properties?: NotebookWorkspaceProperties;
};
/* Properties of a notebook workspace resource. */
export interface NotebookWorkspaceProperties {
/* Specifies the endpoint of Notebook server. */
readonly notebookServerEndpoint?: string;
/* Status of the notebook workspace. Possible values are: Creating, Online, Deleting, Failed, Updating. */
readonly status?: string;
}
/* The connection info for the given notebook workspace */
export interface NotebookWorkspaceConnectionInfoResult {
/* Specifies auth token used for connecting to Notebook server (uses token-based auth). */
readonly authToken?: string;
/* Specifies the endpoint of Notebook server. */
readonly notebookServerEndpoint?: string;
}

View File

@@ -6,7 +6,7 @@ Instead, generate ARM clients that consume this function with stricter typing.
*/
import promiseRetry, { AbortError } from "p-retry";
import { ErrorResponse } from "./generatedClients/2020-04-01/types";
import { ErrorResponse } from "./generatedClients/2020-04-01-cosmos-db/types";
import { userContext } from "../../UserContext";
interface ARMError extends Error {

View File

@@ -1,106 +0,0 @@
import "expect-puppeteer";
import crypto from 'crypto'
jest.setTimeout(300000);
describe('Collection Add and Delete SQL spec', () => {
it('creates a collection', async () => {
try {
const dbId = `TestDatabase${crypto.randomBytes(8).toString("hex")}`;
const collectionId = `TestCollection${crypto.randomBytes(8).toString("hex")}`;
const sharedKey = `SharedKey${crypto.randomBytes(8).toString("hex")}`;
const prodUrl = "https://localhost:1234/hostedExplorer.html";
page.goto(prodUrl);
// log in with connection string
const handle = await page.waitForSelector('iframe');
const frame = await handle.contentFrame();
await frame.waitFor('div > p.switchConnectTypeText', { visible: true });
await frame.click('div > p.switchConnectTypeText');
const connStr = process.env.PORTAL_RUNNER_CONNECTION_STRING;
await frame.type("input[class='inputToken']", connStr);
await frame.click("input[value='Connect']");
// create new collection
await frame.waitFor('button[data-test="New Container"]', { visible: true });
await frame.waitForSelector('div[class="splashScreen"] > div[class="title"]', { visible: true });
await frame.click('button[data-test="New Container"]');
// check new database
await frame.waitFor('input[data-test="addCollection-createNewDatabase"]');
await frame.click('input[data-test="addCollection-createNewDatabase"]');
// check shared throughput
await frame.waitFor('input[data-test="addCollectionPane-databaseSharedThroughput"]');
await frame.click('input[data-test="addCollectionPane-databaseSharedThroughput"]') ;
// type database id
await frame.waitFor('input[data-test="addCollection-newDatabaseId"]');
await frame.type('input[data-test="addCollection-newDatabaseId"]', dbId);
// type collection id
await frame.waitFor('input[data-test="addCollection-collectionId"]');
await frame.type('input[data-test="addCollection-collectionId"]', collectionId);
// type partition key value
await frame.waitFor('input[data-test="addCollection-partitionKeyValue"]');
await frame.type('input[data-test="addCollection-partitionKeyValue"]', sharedKey);
// click submit
await frame.waitFor('#submitBtnAddCollection');
await frame.click('#submitBtnAddCollection');
// validate created
// open database menu
await frame.waitFor(`span[title="${dbId}"]`);
await frame.waitForSelector('div[class="splashScreen"] > div[class="title"]', { visible: true });
await frame.click(`div[data-test="${dbId}"]`);
await frame.waitFor(`span[title="${collectionId}"]`);
// delete container
// click context menu for container
await frame.waitFor(`div[data-test="${collectionId}"] > div > button`);
await frame.click(`div[data-test="${collectionId}"] > div > button`);
// click delete container
await frame.waitForSelector('body > div.ms-Layer.ms-Layer--fixed');
await frame.waitFor(1000);
const elements = await frame.$$('span[class="treeComponentMenuItemLabel"]')
await elements[4].click();
// confirm delete container
await frame.type('input[data-test="confirmCollectionId"]', collectionId.trim());
// click delete
await frame.click('input[data-test="deleteCollection"]');
await frame.waitFor(5000);
await frame.waitForSelector('div[class="splashScreen"] > div[class="title"]', { visible: true });
await expect(page).not.toMatchElement(`div[data-test="${collectionId}"]`);
// click context menu for database
await frame.waitFor(`div[data-test="${dbId}"] > div > button`);
const button = await frame.$(`div[data-test="${dbId}"] > div > button`);
await button.focus();
await button.asElement().click();
// click delete database
await frame.waitFor(1000);
const dbElements = await frame.$$('span[class="treeComponentMenuItemLabel"]')
await dbElements[1].click();
// confirm delete database
await frame.type('input[data-test="confirmDatabaseId"]', dbId.trim());
// click delete
await frame.click('input[data-test="deleteDatabase"]');
await frame.waitForSelector('div[class="splashScreen"] > div[class="title"]', { visible: true });
await expect(page).not.toMatchElement(`div[data-test="${dbId}"]`);
} catch (error) {
await page.screenshot({path: 'failure.png'});
throw error;
}
})
})

View File

@@ -3,7 +3,7 @@ import { trackEvent, trackException } from "./utils";
jest.setTimeout(300000);
describe.skip("Collection CRUD", () => {
describe("Collection CRUD", () => {
it("should complete collection crud", async () => {
try {
// Login to Azure Portal

View File

@@ -68,7 +68,7 @@
"./src/Utils/MessageValidation.ts",
"./src/Utils/OfferUtils.ts",
"./src/Utils/StringUtils.ts",
"./src/Utils/arm/generatedClients/2020-04-01/types.ts",
"./src/Utils/arm/generatedClients/2020-04-01-cosmos-db/types.ts",
"./src/quickstart.ts",
"./src/setupTests.ts",
"./src/workers/upload/definitions.ts"

View File

@@ -14,12 +14,14 @@ But it does work well enough to generate a fully typed tree-shakeable client for
Results of this file should be checked into the repo.
*/
const rpname = "notebook"; // Can also use "notebooks"
// Array of strings to use for eventual output
const outputTypes: string[] = [""];
const version = "2020-04-01";
const schemaURL = `https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/${version}/cosmos-db.json`;
const schemaURL = `https://raw.githubusercontent.com/Azure/azure-rest-api-specs/master/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/stable/${version}/${rpname}.json`;
const outputDir = path.join(__dirname, `../../src/Utils/arm/generatedClients/${version}`);
const outputDir = path.join(__dirname, `../../src/Utils/arm/generatedClients/${version}-${rpname}`);
mkdirp.sync(outputDir);
// Buckets for grouping operations based on their name
@@ -77,12 +79,16 @@ function responseType(operation: Operation, namespace: string) {
if (operation.responses) {
return Object.keys(operation.responses)
.map((responseCode: string) => {
// "default" always seems to be an ErrorResponse which we do not want to include in the possible return type
if (responseCode === "default") {
return undefined;
}
if (!operation.responses[responseCode].schema) {
return "void";
}
return refToType(operation.responses[responseCode].schema.$ref, namespace);
})
.filter((value, index, array) => array.indexOf(value) === index)
.filter((value, index, array) => value && array.indexOf(value) === index) // Ensure all values are truthy and unique
.join(" | ");
}
return "unknown";