mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-10-13 15:28:05 +01:00
upgrade react to v18 and other packages
This commit is contained in:
parent
a5c3e6bea0
commit
695729a8b6
23
.vscode/settings.json
vendored
23
.vscode/settings.json
vendored
@ -1,22 +1,6 @@
|
|||||||
// Place your settings in this file to overwrite default and user settings.
|
// Place your settings in this file to overwrite default and user settings.
|
||||||
{
|
{
|
||||||
"files.exclude": {
|
|
||||||
".vs": true,
|
|
||||||
".vscode/**": true,
|
|
||||||
"*.trx": true,
|
|
||||||
"**/.DS_Store": true,
|
|
||||||
"**/.git": true,
|
|
||||||
"**/.hg": true,
|
|
||||||
"**/.svn": true,
|
|
||||||
"built/**": true,
|
|
||||||
"coverage/**": true,
|
|
||||||
"libs/**": true,
|
|
||||||
"node_modules/**": true,
|
|
||||||
"package-lock.json": true,
|
|
||||||
"quickstart/**": true,
|
|
||||||
"test/out/**": true,
|
|
||||||
"workers/libs/**": true
|
|
||||||
},
|
|
||||||
"typescript.tsdk": "node_modules/typescript/lib",
|
"typescript.tsdk": "node_modules/typescript/lib",
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
@ -24,5 +8,8 @@
|
|||||||
"source.organizeImports": "explicit"
|
"source.organizeImports": "explicit"
|
||||||
},
|
},
|
||||||
"typescript.preferences.importModuleSpecifier": "non-relative",
|
"typescript.preferences.importModuleSpecifier": "non-relative",
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
|
"[typescript]": {
|
||||||
|
"editor.defaultFormatter": "vscode.typescript-language-features"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
37956
package-lock.json
generated
37956
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
346
package.json
346
package.json
@ -4,200 +4,270 @@
|
|||||||
"description": "Cosmos Explorer",
|
"description": "Cosmos Explorer",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/arm-cosmosdb": "9.1.0",
|
"@azure/arm-cosmosdb": "16.3.0",
|
||||||
"@azure/cosmos": "4.5.0",
|
"@azure/cosmos": "4.5.0",
|
||||||
"@azure/cosmos-language-service": "0.0.5",
|
"@azure/cosmos-language-service": "0.0.5",
|
||||||
"@azure/identity": "4.5.0",
|
"@azure/identity": "4.10.1",
|
||||||
"@azure/msal-browser": "2.14.2",
|
"@azure/msal-browser": "4.24.0",
|
||||||
"@babel/plugin-proposal-class-properties": "7.12.1",
|
"@babel/plugin-transform-class-properties": "^7.24.7",
|
||||||
"@babel/plugin-proposal-decorators": "7.12.12",
|
"@babel/plugin-proposal-decorators": "7.28.0",
|
||||||
"@fluentui/react": "8.119.0",
|
"@fluentui/react": "8.123.6",
|
||||||
"@fluentui/react-components": "9.54.2",
|
"@fluentui/react-components": "9.70.0",
|
||||||
"@jupyterlab/services": "6.0.2",
|
"@jupyterlab/services": "7.4.9",
|
||||||
"@jupyterlab/terminal": "3.0.3",
|
"@jupyterlab/terminal": "4.4.9",
|
||||||
"@microsoft/applicationinsights-web": "2.6.1",
|
"@microsoft/applicationinsights-web": "3.3.10",
|
||||||
"@nteract/commutable": "7.5.1",
|
"@nteract/commutable": "7.5.1",
|
||||||
"@nteract/connected-components": "6.8.2",
|
"@nteract/connected-components": "6.9.0",
|
||||||
"@nteract/core": "15.1.9",
|
"@nteract/core": "15.1.9",
|
||||||
"@nteract/data-explorer": "8.0.3",
|
"@nteract/data-explorer": "8.2.12",
|
||||||
"@nteract/directory-listing": "2.0.6",
|
"@nteract/directory-listing": "2.1.0",
|
||||||
"@nteract/dropdown-menu": "1.0.1",
|
"@nteract/dropdown-menu": "1.1.9",
|
||||||
"@nteract/editor": "10.1.12",
|
"@nteract/editor": "10.1.12",
|
||||||
"@nteract/fixtures": "2.3.0",
|
"@nteract/fixtures": "2.3.19",
|
||||||
"@nteract/iron-icons": "1.0.0",
|
"@nteract/iron-icons": "1.0.0",
|
||||||
"@nteract/jupyter-widgets": "2.0.0",
|
"@nteract/jupyter-widgets": "4.1.19",
|
||||||
"@nteract/logos": "1.0.0",
|
"@nteract/logos": "1.0.0",
|
||||||
"@nteract/markdown": "4.6.0",
|
"@nteract/markdown": "4.6.2",
|
||||||
"@nteract/monaco-editor": "3.2.2",
|
"@nteract/monaco-editor": "3.2.2",
|
||||||
"@nteract/octicons": "2.0.0",
|
"@nteract/octicons": "2.0.0",
|
||||||
"@nteract/outputs": "3.0.9",
|
"@nteract/outputs": "5.1.14",
|
||||||
"@nteract/presentational-components": "3.0.7",
|
"@nteract/presentational-components": "3.4.12",
|
||||||
"@nteract/stateful-components": "1.7.0",
|
"@nteract/stateful-components": "1.7.15",
|
||||||
"@nteract/styles": "2.0.2",
|
"@nteract/styles": "2.2.11",
|
||||||
"@nteract/transform-geojson": "5.1.8",
|
"@nteract/transform-geojson": "5.1.13",
|
||||||
"@nteract/transform-model-debug": "5.0.1",
|
"@nteract/transform-model-debug": "5.0.1",
|
||||||
"@nteract/transform-plotly": "6.1.6",
|
"@nteract/transform-plotly": "7.0.1",
|
||||||
"@nteract/transform-vdom": "4.0.11",
|
"@nteract/transform-vdom": "4.0.15",
|
||||||
"@nteract/transform-vega": "7.0.6",
|
"@nteract/transform-vega": "7.0.6",
|
||||||
"@octokit/rest": "17.9.2",
|
"@octokit/rest": "21.1.1",
|
||||||
"@phosphor/widgets": "1.9.3",
|
"@phosphor/widgets": "1.9.3",
|
||||||
"@testing-library/jest-dom": "6.4.6",
|
"@testing-library/jest-dom": "6.8.0",
|
||||||
"@types/lodash": "4.14.171",
|
"@types/lodash": "4.17.20",
|
||||||
"@types/mkdirp": "1.0.1",
|
"@types/mkdirp": "1.0.2",
|
||||||
"@types/node-fetch": "2.5.7",
|
"@types/node-fetch": "2.6.13",
|
||||||
"@xmldom/xmldom": "0.7.13",
|
"@xmldom/xmldom": "0.9.8",
|
||||||
"@xterm/xterm": "5.5.0",
|
"@xterm/xterm": "5.5.0",
|
||||||
"@xterm/addon-fit": "0.10.0",
|
"@xterm/addon-fit": "0.10.0",
|
||||||
"allotment": "1.20.2",
|
"allotment": "1.20.4",
|
||||||
"applicationinsights": "1.8.0",
|
"applicationinsights": "3.12.0",
|
||||||
"bootstrap": "3.4.1",
|
"bootstrap": "3.4.1",
|
||||||
"canvas": "2.11.2",
|
"canvas": "3.2.0",
|
||||||
"clean-webpack-plugin": "4.0.0",
|
"clean-webpack-plugin": "4.0.0",
|
||||||
"clipboard-copy": "4.0.1",
|
"clipboard-copy": "4.0.1",
|
||||||
"copy-webpack-plugin": "11.0.0",
|
"copy-webpack-plugin": "13.0.1",
|
||||||
"crossroads": "0.12.2",
|
"crossroads": "0.12.2",
|
||||||
"css-element-queries": "1.1.1",
|
"css-element-queries": "1.2.3",
|
||||||
"d3": "7.8.5",
|
"d3": "7.9.0",
|
||||||
"datatables.net-colreorder-dt": "1.7.0",
|
"datatables.net-colreorder-dt": "2.1.1",
|
||||||
"datatables.net-dt": "1.13.8",
|
"datatables.net-dt": "2.3.4",
|
||||||
"date-fns": "1.29.0",
|
"date-fns": "4.1.0",
|
||||||
"dayjs": "1.8.19",
|
"dayjs": "1.11.18",
|
||||||
"dom-to-image": "2.6.0",
|
"dom-to-image": "2.6.0",
|
||||||
"dotenv": "8.2.0",
|
"dotenv": "17.2.3",
|
||||||
"eslint-plugin-jest": "27.4.2",
|
"eslint-plugin-jest": "28.14.0",
|
||||||
"eslint-plugin-react": "7.33.2",
|
"eslint-plugin-react": "7.37.5",
|
||||||
"hasher": "1.2.0",
|
"hasher": "1.2.0",
|
||||||
"html2canvas": "1.0.0-rc.5",
|
"html2canvas": "1.4.1",
|
||||||
"i18next": "23.11.5",
|
"i18next": "25.5.2",
|
||||||
"i18next-browser-languagedetector": "6.0.1",
|
"i18next-browser-languagedetector": "8.2.0",
|
||||||
"i18next-http-backend": "1.0.23",
|
"i18next-http-backend": "3.0.2",
|
||||||
"iframe-resizer-react": "1.1.0",
|
"iframe-resizer-react": "5.1.5",
|
||||||
"immer": "9.0.6",
|
"immer": "10.1.3",
|
||||||
"immutable": "4.0.0-rc.12",
|
"immutable": "4.0.0-rc.12",
|
||||||
"is-ci": "2.0.0",
|
"is-ci": "4.1.0",
|
||||||
"jquery": "3.7.1",
|
"jquery": "3.7.1",
|
||||||
"jquery-typeahead": "2.11.1",
|
"jquery-typeahead": "2.11.1",
|
||||||
"jquery-ui-dist": "1.13.2",
|
"jquery-ui-dist": "1.13.3",
|
||||||
"knockout": "3.5.1",
|
"knockout": "3.5.1",
|
||||||
"loader-utils": "2.0.3",
|
"loader-utils": "3.3.1",
|
||||||
"mkdirp": "1.0.4",
|
"mkdirp": "3.0.1",
|
||||||
"monaco-editor": "0.44.0",
|
"monaco-editor": "0.53.0",
|
||||||
"ms": "2.1.3",
|
"ms": "2.1.3",
|
||||||
"p-retry": "6.2.1",
|
"p-retry": "6.2.1",
|
||||||
"patch-package": "8.0.0",
|
"patch-package": "8.0.1",
|
||||||
"plotly.js-cartesian-dist-min": "1.52.3",
|
"plotly.js-cartesian-dist-min": "3.1.1",
|
||||||
"post-robot": "10.0.42",
|
"post-robot": "10.0.42",
|
||||||
"q": "1.5.1",
|
"q": "2.0.3",
|
||||||
"react": "16.14.0",
|
"react": "18.2.0",
|
||||||
"react-animate-height": "2.0.8",
|
"react-animate-height": "3.2.3",
|
||||||
"react-dnd": "14.0.2",
|
"react-dnd": "16.0.1",
|
||||||
"react-dnd-html5-backend": "14.0.0",
|
"react-dnd-html5-backend": "16.0.1",
|
||||||
"react-dom": "16.14.0",
|
"react-dom": "18.2.0",
|
||||||
"react-hotkeys": "2.0.0",
|
"react-hotkeys": "2.0.0",
|
||||||
"react-i18next": "14.1.2",
|
"react-i18next": "16.0.0",
|
||||||
"react-notification-system": "0.2.17",
|
"react-notification-system": "0.2.17",
|
||||||
"react-redux": "7.1.3",
|
"react-redux": "7.2.9",
|
||||||
"react-splitter-layout": "4.0.0",
|
"react-splitter-layout": "4.0.0",
|
||||||
"react-string-format": "1.0.1",
|
"react-string-format": "1.2.0",
|
||||||
"react-window": "1.8.10",
|
"react-window": "1.8.10",
|
||||||
"react-youtube": "9.0.1",
|
"react-youtube": "10.1.0",
|
||||||
"reflect-metadata": "0.1.13",
|
"reflect-metadata": "0.2.2",
|
||||||
"rx-jupyter": "5.5.12",
|
"rx-jupyter": "5.5.21",
|
||||||
"sanitize-html": "2.3.3",
|
"sanitize-html": "2.17.0",
|
||||||
"shell-quote": "1.7.3",
|
"shell-quote": "1.8.3",
|
||||||
"styled-components": "5.0.1",
|
"styled-components": "6.1.19",
|
||||||
"swr": "0.4.0",
|
"swr": "2.3.6",
|
||||||
"terser-webpack-plugin": "5.3.9",
|
"terser-webpack-plugin": "5.3.14",
|
||||||
"tinykeys": "2.1.0",
|
"tinykeys": "3.0.0",
|
||||||
"underscore": "1.12.1",
|
"underscore": "1.13.7",
|
||||||
"utility-types": "3.10.0",
|
"utility-types": "3.11.0",
|
||||||
"zustand": "3.5.0"
|
"zustand": "5.0.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "7.24.7",
|
"@babel/core": "7.28.4",
|
||||||
"@babel/preset-env": "7.24.7",
|
"@babel/preset-env": "7.28.3",
|
||||||
"@babel/preset-react": "7.24.7",
|
"@babel/preset-react": "7.27.1",
|
||||||
"@babel/preset-typescript": "7.24.7",
|
"@babel/preset-typescript": "7.27.1",
|
||||||
"@playwright/test": "1.49.1",
|
"@playwright/test": "1.55.1",
|
||||||
"@testing-library/react": "11.2.3",
|
"@testing-library/react": "16.3.0",
|
||||||
"@types/applicationinsights-js": "1.0.7",
|
"@types/applicationinsights-js": "1.0.9",
|
||||||
"@types/codemirror": "0.0.56",
|
"@types/codemirror": "5.60.16",
|
||||||
"@types/crossroads": "0.0.30",
|
"@types/crossroads": "0.0.33",
|
||||||
"@types/d3": "5.9.2",
|
"@types/d3": "7.4.3",
|
||||||
"@types/datatables.net": "1.10.28",
|
"@types/datatables.net": "1.10.28",
|
||||||
"@types/datatables.net-colreorder": "1.4.5",
|
"@types/datatables.net-colreorder": "1.4.5",
|
||||||
"@types/dom-to-image": "2.6.2",
|
"@types/dom-to-image": "2.6.7",
|
||||||
"@types/enzyme": "3.10.12",
|
"@types/enzyme": "3.10.19",
|
||||||
"@types/enzyme-adapter-react-16": "1.0.9",
|
"@types/enzyme-adapter-react-16": "1.0.9",
|
||||||
"@types/hasher": "0.0.31",
|
"@types/hasher": "0.0.35",
|
||||||
"@types/jest": "29.5.12",
|
"@types/jest": "30.0.0",
|
||||||
"@types/jquery": "3.5.29",
|
"@types/jquery": "3.5.33",
|
||||||
"@types/node": "12.11.1",
|
"@types/node": "24.6.0",
|
||||||
"@types/post-robot": "10.0.1",
|
"@types/post-robot": "10.0.6",
|
||||||
"@types/q": "1.5.1",
|
"@types/q": "1.5.8",
|
||||||
"@types/react": "17.0.44",
|
"@types/react": "18.3.7",
|
||||||
"@types/react-dom": "17.0.15",
|
"@types/react-dom": "18.3.7",
|
||||||
"@types/react-notification-system": "0.2.39",
|
"@types/react-notification-system": "0.2.46",
|
||||||
"@types/react-redux": "7.1.7",
|
"@types/react-redux": "7.1.34",
|
||||||
"@types/react-splitter-layout": "3.0.1",
|
"@types/react-splitter-layout": "4.0.0",
|
||||||
"@types/react-window": "1.8.8",
|
"@types/react-window": "1.8.8",
|
||||||
"@types/sanitize-html": "1.27.2",
|
"@types/sanitize-html": "2.16.0",
|
||||||
"@types/sinon": "2.3.3",
|
"@types/sinon": "17.0.4",
|
||||||
"@types/styled-components": "5.1.1",
|
"@types/styled-components": "5.1.34",
|
||||||
"@types/underscore": "1.7.36",
|
"@types/underscore": "1.13.0",
|
||||||
"@types/youtube-player": "5.5.6",
|
"@types/youtube-player": "5.5.11",
|
||||||
"@typescript-eslint/eslint-plugin": "6.7.4",
|
"@typescript-eslint/eslint-plugin": "8.45.0",
|
||||||
"@typescript-eslint/parser": "6.7.4",
|
"@typescript-eslint/parser": "8.45.0",
|
||||||
"@webpack-cli/serve": "2.0.5",
|
"@webpack-cli/serve": "3.0.1",
|
||||||
"babel-jest": "29.7.0",
|
"babel-jest": "30.2.0",
|
||||||
"babel-loader": "8.1.0",
|
"babel-loader": "10.0.0",
|
||||||
"buffer": "5.1.0",
|
"buffer": "6.0.3",
|
||||||
"case-sensitive-paths-webpack-plugin": "2.4.0",
|
"case-sensitive-paths-webpack-plugin": "2.4.0",
|
||||||
"create-file-webpack": "1.0.2",
|
"create-file-webpack": "1.0.2",
|
||||||
"css-loader": "6.8.1",
|
"css-loader": "7.1.2",
|
||||||
"enzyme": "3.11.0",
|
"enzyme": "3.11.0",
|
||||||
"enzyme-adapter-react-16": "1.15.8",
|
"enzyme-adapter-react-16": "1.15.8",
|
||||||
"enzyme-to-json": "3.6.2",
|
"enzyme-to-json": "3.6.2",
|
||||||
"eslint": "8.50.0",
|
"eslint": "9.36.0",
|
||||||
"eslint-cli": "1.1.1",
|
"eslint-cli": "1.1.1",
|
||||||
"eslint-plugin-no-null": "1.0.2",
|
"eslint-plugin-no-null": "1.0.2",
|
||||||
"eslint-plugin-prefer-arrow": "1.2.3",
|
"eslint-plugin-prefer-arrow": "1.2.3",
|
||||||
"eslint-plugin-react-hooks": "4.6.0",
|
"eslint-plugin-react-hooks": "5.2.0",
|
||||||
"fast-glob": "3.2.5",
|
"fast-glob": "3.3.3",
|
||||||
"fs-extra": "7.0.0",
|
"fs-extra": "11.3.2",
|
||||||
"html-inline-css-webpack-plugin": "1.11.2",
|
"html-inline-css-webpack-plugin": "1.11.2",
|
||||||
"html-loader": "5.0.0",
|
"html-loader": "5.1.0",
|
||||||
"html-webpack-plugin": "5.5.3",
|
"html-webpack-plugin": "5.6.4",
|
||||||
"jest": "29.7.0",
|
"jest": "30.2.0",
|
||||||
"jest-canvas-mock": "2.5.2",
|
"jest-canvas-mock": "2.5.2",
|
||||||
"jest-circus": "29.7.0",
|
"jest-circus": "30.2.0",
|
||||||
"jest-environment-jsdom": "29.7.0",
|
"jest-environment-jsdom": "30.2.0",
|
||||||
"jest-html-loader": "1.0.0",
|
"jest-html-loader": "1.0.0",
|
||||||
"jest-react-hooks-shallow": "1.5.1",
|
"jest-react-hooks-shallow": "1.5.1",
|
||||||
"jest-trx-results-processor": "3.0.2",
|
"jest-trx-results-processor": "3.0.2",
|
||||||
"less": "3.8.1",
|
"less": "4.4.1",
|
||||||
"less-loader": "11.1.3",
|
"less-loader": "12.3.0",
|
||||||
"less-vars-loader": "1.1.0",
|
"less-vars-loader": "1.1.0",
|
||||||
"mini-css-extract-plugin": "2.1.0",
|
"mini-css-extract-plugin": "2.9.4",
|
||||||
"monaco-editor-webpack-plugin": "7.1.0",
|
"monaco-editor-webpack-plugin": "7.1.0",
|
||||||
"node-fetch": "2.6.7",
|
"node-fetch": "3.3.2",
|
||||||
"prettier": "3.0.3",
|
"prettier": "3.6.2",
|
||||||
"process": "0.11.10",
|
"process": "0.11.10",
|
||||||
"querystring-es3": "0.2.1",
|
"querystring-es3": "0.2.1",
|
||||||
"raw-loader": "0.5.1",
|
"raw-loader": "4.0.2",
|
||||||
"react-dev-utils": "12.0.1",
|
"react-dev-utils": "12.0.1",
|
||||||
"rimraf": "3.0.0",
|
"rimraf": "5.0.10",
|
||||||
"sinon": "3.2.1",
|
"sinon": "21.0.0",
|
||||||
"style-loader": "0.23.0",
|
"style-loader": "4.0.0",
|
||||||
"ts-loader": "9.2.4",
|
"ts-loader": "9.5.4",
|
||||||
"typedoc": "0.26.2",
|
"typedoc": "0.28.13",
|
||||||
"typescript": "4.9.5",
|
"typescript": "5.9.2",
|
||||||
"url-loader": "4.1.1",
|
"url-loader": "4.1.1",
|
||||||
"wait-on": "4.0.2",
|
"wait-on": "8.0.5",
|
||||||
"webpack": "5.88.2",
|
"webpack": "5.102.0",
|
||||||
"webpack-bundle-analyzer": "4.9.1",
|
"webpack-bundle-analyzer": "4.10.2",
|
||||||
"webpack-cli": "5.1.4",
|
"webpack-cli": "6.0.1",
|
||||||
"webpack-dev-server": "4.15.2"
|
"webpack-dev-server": "5.2.2"
|
||||||
|
},
|
||||||
|
"overrides": {
|
||||||
|
"@nteract/connected-components": {
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0"
|
||||||
|
},
|
||||||
|
"@nteract/core": {
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0"
|
||||||
|
},
|
||||||
|
"@nteract/data-explorer": {
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0"
|
||||||
|
},
|
||||||
|
"@nteract/dropdown-menu": {
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0"
|
||||||
|
},
|
||||||
|
"@nteract/editor": {
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0"
|
||||||
|
},
|
||||||
|
"@nteract/iron-icons": {
|
||||||
|
"react": "18.2.0"
|
||||||
|
},
|
||||||
|
"@nteract/jupyter-widgets": {
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0"
|
||||||
|
},
|
||||||
|
"@nteract/logos": {
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0"
|
||||||
|
},
|
||||||
|
"@nteract/markdown": {
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0"
|
||||||
|
},
|
||||||
|
"@nteract/monaco-editor": {
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0"
|
||||||
|
},
|
||||||
|
"@nteract/octicons": {
|
||||||
|
"react": "18.2.0"
|
||||||
|
},
|
||||||
|
"@nteract/outputs": {
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0"
|
||||||
|
},
|
||||||
|
"@nteract/presentational-components": {
|
||||||
|
"react": "18.2.0"
|
||||||
|
},
|
||||||
|
"@nteract/stateful-components": {
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0"
|
||||||
|
},
|
||||||
|
"@nteract/transform-geojson": {
|
||||||
|
"react": "18.2.0"
|
||||||
|
},
|
||||||
|
"@nteract/transform-model-debug": {
|
||||||
|
"react": "18.2.0"
|
||||||
|
},
|
||||||
|
"@nteract/transform-plotly": {
|
||||||
|
"react": "18.2.0"
|
||||||
|
},
|
||||||
|
"@nteract/transform-vdom": {
|
||||||
|
"react": "18.2.0"
|
||||||
|
},
|
||||||
|
"@nteract/transform-vega": {
|
||||||
|
"react": "18.2.0"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"postinstall": "patch-package",
|
"postinstall": "patch-package",
|
||||||
|
@ -6,9 +6,9 @@ index e5dc283..1930c2b 100644
|
|||||||
|
|
||||||
/// <reference types="jquery" />
|
/// <reference types="jquery" />
|
||||||
|
|
||||||
-import DataTables, {Api} from 'datatables.net';
|
-import DataTables, {Api, ColumnSelector} from 'datatables.net';
|
||||||
+import DataTables, { Api } from 'datatables.net';
|
+import DataTables, { Api, ColumnSelector } from 'datatables.net';
|
||||||
|
|
||||||
export default DataTables;
|
export default DataTables;
|
||||||
|
|
||||||
@@ -40,6 +40,8 @@ declare module 'datatables.net' {
|
@@ -40,6 +40,8 @@ declare module 'datatables.net' {
|
||||||
@ -17,6 +17,6 @@ index e5dc283..1930c2b 100644
|
|||||||
*/
|
*/
|
||||||
+ // Ignore this error: error TS7013: Construct signature, which lacks return-type annotation, implicitly has an 'any' return type.
|
+ // Ignore this error: error TS7013: Construct signature, which lacks return-type annotation, implicitly has an 'any' return type.
|
||||||
+ // @ts-ignore
|
+ // @ts-ignore
|
||||||
new (dt: Api<any>, settings: boolean | ConfigColReorder);
|
new (dt: Api<any>, settings: boolean | ConfigColReorder): DataTablesStatic['ColReorder'];
|
||||||
|
|
||||||
/**
|
/**
|
@ -16,7 +16,7 @@ import {
|
|||||||
TextField,
|
TextField,
|
||||||
} from "@fluentui/react";
|
} from "@fluentui/react";
|
||||||
import React, { FC, useEffect } from "react";
|
import React, { FC, useEffect } from "react";
|
||||||
import create, { UseStore } from "zustand";
|
import { create } from "zustand";
|
||||||
|
|
||||||
export interface DialogState {
|
export interface DialogState {
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
@ -38,7 +38,7 @@ export interface DialogState {
|
|||||||
showOkModalDialog: (title: string, subText: string, linkProps?: LinkProps) => void;
|
showOkModalDialog: (title: string, subText: string, linkProps?: LinkProps) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useDialog: UseStore<DialogState> = create((set, get) => ({
|
export const useDialog = create<DialogState>((set, get) => ({
|
||||||
visible: false,
|
visible: false,
|
||||||
openDialog: (props: DialogProps) => set(() => ({ visible: true, dialogProps: props })),
|
openDialog: (props: DialogProps) => set(() => ({ visible: true, dialogProps: props })),
|
||||||
closeDialog: () =>
|
closeDialog: () =>
|
||||||
|
@ -23,7 +23,7 @@ import { useQueryCopilot } from "hooks/useQueryCopilot";
|
|||||||
import * as ko from "knockout";
|
import * as ko from "knockout";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import _ from "underscore";
|
import _ from "underscore";
|
||||||
import shallow from "zustand/shallow";
|
import { shallow } from "zustand/shallow";
|
||||||
import { AuthType } from "../AuthType";
|
import { AuthType } from "../AuthType";
|
||||||
import { BindingHandlersRegisterer } from "../Bindings/BindingHandlersRegisterer";
|
import { BindingHandlersRegisterer } from "../Bindings/BindingHandlersRegisterer";
|
||||||
import * as Constants from "../Common/Constants";
|
import * as Constants from "../Common/Constants";
|
||||||
@ -112,8 +112,8 @@ export default class Explorer {
|
|||||||
|
|
||||||
this.phoenixClient = new PhoenixClient(userContext?.databaseAccount?.id);
|
this.phoenixClient = new PhoenixClient(userContext?.databaseAccount?.id);
|
||||||
useNotebook.subscribe(
|
useNotebook.subscribe(
|
||||||
() => this.refreshCommandBarButtons(),
|
|
||||||
(state) => state.isNotebooksEnabledForAccount,
|
(state) => state.isNotebooksEnabledForAccount,
|
||||||
|
() => this.refreshCommandBarButtons(),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.queriesClient = new QueriesClient(this);
|
this.queriesClient = new QueriesClient(this);
|
||||||
@ -136,13 +136,13 @@ export default class Explorer {
|
|||||||
});
|
});
|
||||||
|
|
||||||
useTabs.subscribe(
|
useTabs.subscribe(
|
||||||
|
(state) => state.openedTabs,
|
||||||
(openedTabs: TabsBase[]) => {
|
(openedTabs: TabsBase[]) => {
|
||||||
if (openedTabs.length === 0) {
|
if (openedTabs.length === 0) {
|
||||||
useSelectedNode.getState().setSelectedNode(undefined);
|
useSelectedNode.getState().setSelectedNode(undefined);
|
||||||
useCommandBar.getState().setContextButtons([]);
|
useCommandBar.getState().setContextButtons([]);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
(state) => state.openedTabs,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
this.isTabsContentExpanded = ko.observable(false);
|
this.isTabsContentExpanded = ko.observable(false);
|
||||||
@ -170,9 +170,9 @@ export default class Explorer {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useNotebook.subscribe(
|
useNotebook.subscribe(
|
||||||
async () => this.initiateAndRefreshNotebookList(),
|
|
||||||
(state) => [state.isNotebookEnabled, state.isRefreshed],
|
(state) => [state.isNotebookEnabled, state.isRefreshed],
|
||||||
shallow,
|
async () => this.initiateAndRefreshNotebookList(),
|
||||||
|
{ equalityFn: shallow },
|
||||||
);
|
);
|
||||||
|
|
||||||
this.resourceTree = new ResourceTreeAdapter(this);
|
this.resourceTree = new ResourceTreeAdapter(this);
|
||||||
|
@ -10,7 +10,7 @@ import { KeyboardActionGroup, useKeyboardActionGroup } from "KeyboardShortcuts";
|
|||||||
import { isFabric } from "Platform/Fabric/FabricUtil";
|
import { isFabric } from "Platform/Fabric/FabricUtil";
|
||||||
import { userContext } from "UserContext";
|
import { userContext } from "UserContext";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import create, { UseStore } from "zustand";
|
import { create } from "zustand";
|
||||||
import { ConnectionStatusType, PoolIdType } from "../../../Common/Constants";
|
import { ConnectionStatusType, PoolIdType } from "../../../Common/Constants";
|
||||||
import { StyleConstants } from "../../../Common/StyleConstants";
|
import { StyleConstants } from "../../../Common/StyleConstants";
|
||||||
import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent";
|
import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent";
|
||||||
@ -30,7 +30,7 @@ export interface CommandBarStore {
|
|||||||
setIsHidden: (isHidden: boolean) => void;
|
setIsHidden: (isHidden: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useCommandBar: UseStore<CommandBarStore> = create((set) => ({
|
export const useCommandBar = create<CommandBarStore>((set) => ({
|
||||||
contextButtons: [] as CommandButtonComponentProps[],
|
contextButtons: [] as CommandButtonComponentProps[],
|
||||||
setContextButtons: (contextButtons: CommandButtonComponentProps[]) => set((state) => ({ ...state, contextButtons })),
|
setContextButtons: (contextButtons: CommandButtonComponentProps[]) => set((state) => ({ ...state, contextButtons })),
|
||||||
isHidden: false,
|
isHidden: false,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { AppState, ContentRef, selectors } from "@nteract/core";
|
import { AppState, ContentRef, selectors } from "@nteract/core";
|
||||||
import distanceInWordsToNow from "date-fns/distance_in_words_to_now";
|
import { formatDistanceToNow } from "date-fns";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
@ -59,7 +59,7 @@ export class StatusBar extends React.Component<Props> {
|
|||||||
<Bar data-test="notebookStatusBar">
|
<Bar data-test="notebookStatusBar">
|
||||||
<RightStatus>
|
<RightStatus>
|
||||||
{this.props.lastSaved ? (
|
{this.props.lastSaved ? (
|
||||||
<p data-test="saveStatus"> Last saved {distanceInWordsToNow(this.props.lastSaved)} </p>
|
<p data-test="saveStatus"> Last saved {formatDistanceToNow(this.props.lastSaved)} ago </p>
|
||||||
) : (
|
) : (
|
||||||
<p> Not saved yet </p>
|
<p> Not saved yet </p>
|
||||||
)}
|
)}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { isPublicInternetAccessAllowed } from "Common/DatabaseAccountUtility";
|
import { isPublicInternetAccessAllowed } from "Common/DatabaseAccountUtility";
|
||||||
import { PhoenixClient } from "Phoenix/PhoenixClient";
|
import { PhoenixClient } from "Phoenix/PhoenixClient";
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
import create, { UseStore } from "zustand";
|
import { create } from "zustand";
|
||||||
|
import { subscribeWithSelector } from 'zustand/middleware';
|
||||||
import { AuthType } from "../../AuthType";
|
import { AuthType } from "../../AuthType";
|
||||||
import * as Constants from "../../Common/Constants";
|
import * as Constants from "../../Common/Constants";
|
||||||
import { ConnectionStatusType, HttpStatusCodes } from "../../Common/Constants";
|
import { ConnectionStatusType, HttpStatusCodes } from "../../Common/Constants";
|
||||||
@ -66,270 +67,274 @@ interface NotebookState {
|
|||||||
setIsPhoenixFeatures: (isPhoenixFeatures: boolean) => void;
|
setIsPhoenixFeatures: (isPhoenixFeatures: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useNotebook: UseStore<NotebookState> = create((set, get) => ({
|
export const useNotebook = create<NotebookState>()(
|
||||||
isNotebookEnabled: false,
|
subscribeWithSelector(
|
||||||
isNotebooksEnabledForAccount: false,
|
(set, get) => ({
|
||||||
notebookServerInfo: {
|
isNotebookEnabled: false,
|
||||||
notebookServerEndpoint: undefined,
|
isNotebooksEnabledForAccount: false,
|
||||||
authToken: undefined,
|
notebookServerInfo: {
|
||||||
forwardingId: undefined,
|
notebookServerEndpoint: "",
|
||||||
},
|
authToken: "",
|
||||||
sparkClusterConnectionInfo: {
|
forwardingId: "",
|
||||||
userName: undefined,
|
},
|
||||||
password: undefined,
|
sparkClusterConnectionInfo: {
|
||||||
endpoints: [],
|
userName: "",
|
||||||
},
|
password: "",
|
||||||
isSynapseLinkUpdating: false,
|
endpoints: [] as DataModels.SparkClusterEndpoint[],
|
||||||
memoryUsageInfo: undefined,
|
},
|
||||||
isShellEnabled: false,
|
isSynapseLinkUpdating: false,
|
||||||
notebookBasePath: Constants.Notebook.defaultBasePath,
|
memoryUsageInfo: undefined as DataModels.MemoryUsageInfo,
|
||||||
isInitializingNotebooks: false,
|
isShellEnabled: false,
|
||||||
myNotebooksContentRoot: undefined,
|
notebookBasePath: Constants.Notebook.defaultBasePath,
|
||||||
gitHubNotebooksContentRoot: undefined,
|
isInitializingNotebooks: false,
|
||||||
galleryContentRoot: undefined,
|
myNotebooksContentRoot: undefined as NotebookContentItem,
|
||||||
connectionInfo: {
|
gitHubNotebooksContentRoot: undefined as NotebookContentItem,
|
||||||
status: ConnectionStatusType.Connect,
|
galleryContentRoot: undefined as NotebookContentItem,
|
||||||
},
|
connectionInfo: {
|
||||||
notebookFolderName: undefined,
|
status: ConnectionStatusType.Connect,
|
||||||
isAllocating: false,
|
},
|
||||||
isRefreshed: false,
|
notebookFolderName: "",
|
||||||
containerStatus: {
|
isAllocating: false,
|
||||||
status: undefined,
|
isRefreshed: false,
|
||||||
durationLeftInMinutes: undefined,
|
containerStatus: {
|
||||||
phoenixServerInfo: undefined,
|
status: undefined,
|
||||||
},
|
durationLeftInMinutes: undefined,
|
||||||
isPhoenixNotebooks: undefined,
|
phoenixServerInfo: undefined,
|
||||||
isPhoenixFeatures: undefined,
|
} as ContainerInfo,
|
||||||
setIsNotebookEnabled: (isNotebookEnabled: boolean) => set({ isNotebookEnabled }),
|
isPhoenixNotebooks: undefined as boolean,
|
||||||
setIsNotebooksEnabledForAccount: (isNotebooksEnabledForAccount: boolean) => set({ isNotebooksEnabledForAccount }),
|
isPhoenixFeatures: undefined as boolean,
|
||||||
setNotebookServerInfo: (notebookServerInfo: DataModels.NotebookWorkspaceConnectionInfo) =>
|
setIsNotebookEnabled: (isNotebookEnabled: boolean) => set({ isNotebookEnabled }),
|
||||||
set({ notebookServerInfo }),
|
setIsNotebooksEnabledForAccount: (isNotebooksEnabledForAccount: boolean) => set({ isNotebooksEnabledForAccount }),
|
||||||
setSparkClusterConnectionInfo: (sparkClusterConnectionInfo: DataModels.SparkClusterConnectionInfo) =>
|
setNotebookServerInfo: (notebookServerInfo: DataModels.NotebookWorkspaceConnectionInfo) =>
|
||||||
set({ sparkClusterConnectionInfo }),
|
set({ notebookServerInfo }),
|
||||||
setIsSynapseLinkUpdating: (isSynapseLinkUpdating: boolean) => set({ isSynapseLinkUpdating }),
|
setSparkClusterConnectionInfo: (sparkClusterConnectionInfo: DataModels.SparkClusterConnectionInfo) =>
|
||||||
setMemoryUsageInfo: (memoryUsageInfo: DataModels.MemoryUsageInfo) => set({ memoryUsageInfo }),
|
set({ sparkClusterConnectionInfo }),
|
||||||
setIsShellEnabled: (isShellEnabled: boolean) => set({ isShellEnabled }),
|
setIsSynapseLinkUpdating: (isSynapseLinkUpdating: boolean) => set({ isSynapseLinkUpdating }),
|
||||||
setNotebookBasePath: (notebookBasePath: string) => set({ notebookBasePath }),
|
setMemoryUsageInfo: (memoryUsageInfo: DataModels.MemoryUsageInfo) => set({ memoryUsageInfo }),
|
||||||
setNotebookFolderName: (notebookFolderName: string) => set({ notebookFolderName }),
|
setIsShellEnabled: (isShellEnabled: boolean) => set({ isShellEnabled }),
|
||||||
refreshNotebooksEnabledStateForAccount: async (): Promise<void> => {
|
setNotebookBasePath: (notebookBasePath: string) => set({ notebookBasePath }),
|
||||||
await get().getPhoenixStatus();
|
setNotebookFolderName: (notebookFolderName: string) => set({ notebookFolderName }),
|
||||||
const { databaseAccount, authType } = userContext;
|
refreshNotebooksEnabledStateForAccount: async (): Promise<void> => {
|
||||||
if (
|
await get().getPhoenixStatus();
|
||||||
authType === AuthType.EncryptedToken ||
|
const { databaseAccount, authType } = userContext;
|
||||||
authType === AuthType.ResourceToken ||
|
if (
|
||||||
authType === AuthType.MasterKey
|
authType === AuthType.EncryptedToken ||
|
||||||
) {
|
authType === AuthType.ResourceToken ||
|
||||||
set({ isNotebooksEnabledForAccount: false });
|
authType === AuthType.MasterKey
|
||||||
return;
|
) {
|
||||||
}
|
set({ isNotebooksEnabledForAccount: false });
|
||||||
|
return;
|
||||||
const firstWriteLocation =
|
|
||||||
userContext.apiType === "Postgres" || userContext.apiType === "VCoreMongo"
|
|
||||||
? databaseAccount?.location
|
|
||||||
: databaseAccount?.properties?.writeLocations?.[0]?.locationName.toLowerCase();
|
|
||||||
const disallowedLocationsUri: string = `${configContext.PORTAL_BACKEND_ENDPOINT}/api/disallowedlocations`;
|
|
||||||
const authorizationHeader = getAuthorizationHeader();
|
|
||||||
try {
|
|
||||||
const response = await fetch(disallowedLocationsUri, {
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify({
|
|
||||||
resourceTypes: [Constants.ArmResourceTypes.notebookWorkspaces],
|
|
||||||
}),
|
|
||||||
headers: {
|
|
||||||
[authorizationHeader.header]: authorizationHeader.token,
|
|
||||||
[Constants.HttpHeaders.contentType]: "application/json",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error("Failed to fetch disallowed locations");
|
|
||||||
}
|
|
||||||
|
|
||||||
const disallowedLocations: string[] = await response.json();
|
|
||||||
if (!disallowedLocations) {
|
|
||||||
Logger.logInfo("No disallowed locations found", "Explorer/isNotebooksEnabledForAccount");
|
|
||||||
set({ isNotebooksEnabledForAccount: true });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// firstWriteLocation should not be disallowed
|
|
||||||
const isAccountInAllowedLocation = firstWriteLocation && disallowedLocations.indexOf(firstWriteLocation) === -1;
|
|
||||||
set({ isNotebooksEnabledForAccount: isAccountInAllowedLocation });
|
|
||||||
} catch (error) {
|
|
||||||
Logger.logError(getErrorMessage(error), "Explorer/isNotebooksEnabledForAccount");
|
|
||||||
set({ isNotebooksEnabledForAccount: false });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
findItem: (root: NotebookContentItem, item: NotebookContentItem): NotebookContentItem => {
|
|
||||||
const currentItem = root || get().myNotebooksContentRoot;
|
|
||||||
|
|
||||||
if (currentItem) {
|
|
||||||
if (currentItem.path === item.path && currentItem.name === item.name) {
|
|
||||||
return currentItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentItem.children) {
|
|
||||||
for (const childItem of currentItem.children) {
|
|
||||||
const result = get().findItem(childItem, item);
|
|
||||||
if (result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
const firstWriteLocation =
|
||||||
},
|
userContext.apiType === "Postgres" || userContext.apiType === "VCoreMongo"
|
||||||
insertNotebookItem: (parent: NotebookContentItem, item: NotebookContentItem, isGithubTree?: boolean): void => {
|
? databaseAccount?.location
|
||||||
const root = isGithubTree ? cloneDeep(get().gitHubNotebooksContentRoot) : cloneDeep(get().myNotebooksContentRoot);
|
: databaseAccount?.properties?.writeLocations?.[0]?.locationName.toLowerCase();
|
||||||
const parentItem = get().findItem(root, parent);
|
const disallowedLocationsUri: string = `${configContext.PORTAL_BACKEND_ENDPOINT}/api/disallowedlocations`;
|
||||||
item.parent = parentItem;
|
const authorizationHeader = getAuthorizationHeader();
|
||||||
if (parentItem.children) {
|
try {
|
||||||
parentItem.children.push(item);
|
const response = await fetch(disallowedLocationsUri, {
|
||||||
} else {
|
method: "POST",
|
||||||
parentItem.children = [item];
|
body: JSON.stringify({
|
||||||
}
|
resourceTypes: [Constants.ArmResourceTypes.notebookWorkspaces],
|
||||||
isGithubTree ? set({ gitHubNotebooksContentRoot: root }) : set({ myNotebooksContentRoot: root });
|
}),
|
||||||
},
|
headers: {
|
||||||
updateNotebookItem: (item: NotebookContentItem, isGithubTree?: boolean): void => {
|
[authorizationHeader.header]: authorizationHeader.token,
|
||||||
const root = isGithubTree ? cloneDeep(get().gitHubNotebooksContentRoot) : cloneDeep(get().myNotebooksContentRoot);
|
[Constants.HttpHeaders.contentType]: "application/json",
|
||||||
const parentItem = get().findItem(root, item.parent);
|
},
|
||||||
parentItem.children = parentItem.children.filter((child) => child.path !== item.path);
|
|
||||||
parentItem.children.push(item);
|
|
||||||
item.parent = parentItem;
|
|
||||||
isGithubTree ? set({ gitHubNotebooksContentRoot: root }) : set({ myNotebooksContentRoot: root });
|
|
||||||
},
|
|
||||||
deleteNotebookItem: (item: NotebookContentItem, isGithubTree?: boolean): void => {
|
|
||||||
const root = isGithubTree ? cloneDeep(get().gitHubNotebooksContentRoot) : cloneDeep(get().myNotebooksContentRoot);
|
|
||||||
const parentItem = get().findItem(root, item.parent);
|
|
||||||
parentItem.children = parentItem.children.filter((child) => child.path !== item.path);
|
|
||||||
isGithubTree ? set({ gitHubNotebooksContentRoot: root }) : set({ myNotebooksContentRoot: root });
|
|
||||||
},
|
|
||||||
initializeNotebooksTree: async (notebookManager: NotebookManager): Promise<void> => {
|
|
||||||
const notebookFolderName = get().isPhoenixNotebooks ? "Temporary Notebooks" : "My Notebooks";
|
|
||||||
set({ notebookFolderName });
|
|
||||||
const myNotebooksContentRoot = {
|
|
||||||
name: get().notebookFolderName,
|
|
||||||
path: get().notebookBasePath,
|
|
||||||
type: NotebookContentItemType.Directory,
|
|
||||||
};
|
|
||||||
const galleryContentRoot = {
|
|
||||||
name: "Gallery",
|
|
||||||
path: "Gallery",
|
|
||||||
type: NotebookContentItemType.File,
|
|
||||||
};
|
|
||||||
const gitHubNotebooksContentRoot = notebookManager?.gitHubOAuthService?.isLoggedIn()
|
|
||||||
? {
|
|
||||||
name: "GitHub repos",
|
|
||||||
path: "PsuedoDir",
|
|
||||||
type: NotebookContentItemType.Directory,
|
|
||||||
}
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
set({
|
|
||||||
myNotebooksContentRoot,
|
|
||||||
galleryContentRoot,
|
|
||||||
gitHubNotebooksContentRoot,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (get().notebookServerInfo?.notebookServerEndpoint) {
|
|
||||||
const updatedRoot = await notebookManager?.notebookContentClient?.updateItemChildren(myNotebooksContentRoot);
|
|
||||||
set({ myNotebooksContentRoot: updatedRoot });
|
|
||||||
|
|
||||||
if (updatedRoot?.children) {
|
|
||||||
// Count 1st generation children (tree is lazy-loaded)
|
|
||||||
const nodeCounts = { files: 0, notebooks: 0, directories: 0 };
|
|
||||||
updatedRoot.children.forEach((notebookItem) => {
|
|
||||||
switch (notebookItem.type) {
|
|
||||||
case NotebookContentItemType.File:
|
|
||||||
nodeCounts.files++;
|
|
||||||
break;
|
|
||||||
case NotebookContentItemType.Directory:
|
|
||||||
nodeCounts.directories++;
|
|
||||||
break;
|
|
||||||
case NotebookContentItemType.Notebook:
|
|
||||||
nodeCounts.notebooks++;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
TelemetryProcessor.trace(Action.RefreshResourceTreeMyNotebooks, ActionModifiers.Mark, { ...nodeCounts });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
initializeGitHubRepos: (pinnedRepos: IPinnedRepo[]): void => {
|
|
||||||
const gitHubNotebooksContentRoot = cloneDeep(get().gitHubNotebooksContentRoot);
|
|
||||||
if (gitHubNotebooksContentRoot) {
|
|
||||||
gitHubNotebooksContentRoot.children = [];
|
|
||||||
pinnedRepos?.forEach((pinnedRepo) => {
|
|
||||||
const repoFullName = GitHubUtils.toRepoFullName(pinnedRepo.owner, pinnedRepo.name);
|
|
||||||
const repoTreeItem: NotebookContentItem = {
|
|
||||||
name: repoFullName,
|
|
||||||
path: "PsuedoDir",
|
|
||||||
type: NotebookContentItemType.Directory,
|
|
||||||
children: [],
|
|
||||||
parent: gitHubNotebooksContentRoot,
|
|
||||||
};
|
|
||||||
|
|
||||||
pinnedRepo.branches.forEach((branch) => {
|
|
||||||
repoTreeItem.children.push({
|
|
||||||
name: branch.name,
|
|
||||||
path: GitHubUtils.toContentUri(pinnedRepo.owner, pinnedRepo.name, branch.name, ""),
|
|
||||||
type: NotebookContentItemType.Directory,
|
|
||||||
parent: repoTreeItem,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to fetch disallowed locations");
|
||||||
|
}
|
||||||
|
|
||||||
|
const disallowedLocations: string[] = await response.json();
|
||||||
|
if (!disallowedLocations) {
|
||||||
|
Logger.logInfo("No disallowed locations found", "Explorer/isNotebooksEnabledForAccount");
|
||||||
|
set({ isNotebooksEnabledForAccount: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// firstWriteLocation should not be disallowed
|
||||||
|
const isAccountInAllowedLocation = firstWriteLocation && disallowedLocations.indexOf(firstWriteLocation) === -1;
|
||||||
|
set({ isNotebooksEnabledForAccount: isAccountInAllowedLocation });
|
||||||
|
} catch (error) {
|
||||||
|
Logger.logError(getErrorMessage(error), "Explorer/isNotebooksEnabledForAccount");
|
||||||
|
set({ isNotebooksEnabledForAccount: false });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
findItem: (root: NotebookContentItem, item: NotebookContentItem): NotebookContentItem => {
|
||||||
|
const currentItem = root || get().myNotebooksContentRoot;
|
||||||
|
|
||||||
|
if (currentItem) {
|
||||||
|
if (currentItem.path === item.path && currentItem.name === item.name) {
|
||||||
|
return currentItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentItem.children) {
|
||||||
|
for (const childItem of currentItem.children) {
|
||||||
|
const result = get().findItem(childItem, item);
|
||||||
|
if (result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
|
insertNotebookItem: (parent: NotebookContentItem, item: NotebookContentItem, isGithubTree?: boolean): void => {
|
||||||
|
const root = isGithubTree ? cloneDeep(get().gitHubNotebooksContentRoot) : cloneDeep(get().myNotebooksContentRoot);
|
||||||
|
const parentItem = get().findItem(root, parent);
|
||||||
|
item.parent = parentItem;
|
||||||
|
if (parentItem.children) {
|
||||||
|
parentItem.children.push(item);
|
||||||
|
} else {
|
||||||
|
parentItem.children = [item];
|
||||||
|
}
|
||||||
|
isGithubTree ? set({ gitHubNotebooksContentRoot: root }) : set({ myNotebooksContentRoot: root });
|
||||||
|
},
|
||||||
|
updateNotebookItem: (item: NotebookContentItem, isGithubTree?: boolean): void => {
|
||||||
|
const root = isGithubTree ? cloneDeep(get().gitHubNotebooksContentRoot) : cloneDeep(get().myNotebooksContentRoot);
|
||||||
|
const parentItem = get().findItem(root, item.parent);
|
||||||
|
parentItem.children = parentItem.children.filter((child) => child.path !== item.path);
|
||||||
|
parentItem.children.push(item);
|
||||||
|
item.parent = parentItem;
|
||||||
|
isGithubTree ? set({ gitHubNotebooksContentRoot: root }) : set({ myNotebooksContentRoot: root });
|
||||||
|
},
|
||||||
|
deleteNotebookItem: (item: NotebookContentItem, isGithubTree?: boolean): void => {
|
||||||
|
const root = isGithubTree ? cloneDeep(get().gitHubNotebooksContentRoot) : cloneDeep(get().myNotebooksContentRoot);
|
||||||
|
const parentItem = get().findItem(root, item.parent);
|
||||||
|
parentItem.children = parentItem.children.filter((child) => child.path !== item.path);
|
||||||
|
isGithubTree ? set({ gitHubNotebooksContentRoot: root }) : set({ myNotebooksContentRoot: root });
|
||||||
|
},
|
||||||
|
initializeNotebooksTree: async (notebookManager: NotebookManager): Promise<void> => {
|
||||||
|
const notebookFolderName = get().isPhoenixNotebooks ? "Temporary Notebooks" : "My Notebooks";
|
||||||
|
set({ notebookFolderName });
|
||||||
|
const myNotebooksContentRoot = {
|
||||||
|
name: get().notebookFolderName,
|
||||||
|
path: get().notebookBasePath,
|
||||||
|
type: NotebookContentItemType.Directory,
|
||||||
|
};
|
||||||
|
const galleryContentRoot = {
|
||||||
|
name: "Gallery",
|
||||||
|
path: "Gallery",
|
||||||
|
type: NotebookContentItemType.File,
|
||||||
|
};
|
||||||
|
const gitHubNotebooksContentRoot = notebookManager?.gitHubOAuthService?.isLoggedIn()
|
||||||
|
? {
|
||||||
|
name: "GitHub repos",
|
||||||
|
path: "PsuedoDir",
|
||||||
|
type: NotebookContentItemType.Directory,
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
set({
|
||||||
|
myNotebooksContentRoot,
|
||||||
|
galleryContentRoot,
|
||||||
|
gitHubNotebooksContentRoot,
|
||||||
});
|
});
|
||||||
|
|
||||||
gitHubNotebooksContentRoot.children.push(repoTreeItem);
|
if (get().notebookServerInfo?.notebookServerEndpoint) {
|
||||||
});
|
const updatedRoot = await notebookManager?.notebookContentClient?.updateItemChildren(myNotebooksContentRoot);
|
||||||
|
set({ myNotebooksContentRoot: updatedRoot });
|
||||||
|
|
||||||
set({ gitHubNotebooksContentRoot });
|
if (updatedRoot?.children) {
|
||||||
}
|
// Count 1st generation children (tree is lazy-loaded)
|
||||||
},
|
const nodeCounts = { files: 0, notebooks: 0, directories: 0 };
|
||||||
setConnectionInfo: (connectionInfo: ContainerConnectionInfo) => set({ connectionInfo }),
|
updatedRoot.children.forEach((notebookItem) => {
|
||||||
setIsAllocating: (isAllocating: boolean) => set({ isAllocating }),
|
switch (notebookItem.type) {
|
||||||
resetContainerConnection: (connectionStatus: ContainerConnectionInfo): void => {
|
case NotebookContentItemType.File:
|
||||||
useTabs.getState().closeAllNotebookTabs(true);
|
nodeCounts.files++;
|
||||||
useNotebook.getState().setConnectionInfo(connectionStatus);
|
break;
|
||||||
useNotebook.getState().setNotebookServerInfo(undefined);
|
case NotebookContentItemType.Directory:
|
||||||
useNotebook.getState().setIsAllocating(false);
|
nodeCounts.directories++;
|
||||||
useNotebook.getState().setContainerStatus({
|
break;
|
||||||
status: undefined,
|
case NotebookContentItemType.Notebook:
|
||||||
durationLeftInMinutes: undefined,
|
nodeCounts.notebooks++;
|
||||||
phoenixServerInfo: undefined,
|
break;
|
||||||
});
|
default:
|
||||||
},
|
break;
|
||||||
setIsRefreshed: (isRefreshed: boolean) => set({ isRefreshed }),
|
}
|
||||||
setContainerStatus: (containerStatus: ContainerInfo) => set({ containerStatus }),
|
});
|
||||||
getPhoenixStatus: async () => {
|
TelemetryProcessor.trace(Action.RefreshResourceTreeMyNotebooks, ActionModifiers.Mark, { ...nodeCounts });
|
||||||
if (get().isPhoenixNotebooks === undefined || get().isPhoenixFeatures === undefined) {
|
}
|
||||||
let isPhoenixNotebooks = false;
|
|
||||||
let isPhoenixFeatures = false;
|
|
||||||
|
|
||||||
const isPublicInternetAllowed = isPublicInternetAccessAllowed();
|
|
||||||
const phoenixClient = new PhoenixClient(userContext?.databaseAccount?.id);
|
|
||||||
const dbAccountAllowedInfo = await phoenixClient.getDbAccountAllowedStatus();
|
|
||||||
|
|
||||||
if (dbAccountAllowedInfo.status === HttpStatusCodes.OK) {
|
|
||||||
if (dbAccountAllowedInfo?.type === PhoenixErrorType.PhoenixFlightFallback) {
|
|
||||||
isPhoenixNotebooks = isPublicInternetAllowed && userContext.features.phoenixNotebooks === true;
|
|
||||||
isPhoenixFeatures =
|
|
||||||
isPublicInternetAllowed &&
|
|
||||||
// phoenix needs to be enabled for Postgres and VCoreMongo accounts since the PSQL and mongo shell requires phoenix containers
|
|
||||||
(userContext.features.phoenixFeatures === true ||
|
|
||||||
userContext.apiType === "Postgres" ||
|
|
||||||
userContext.apiType === "VCoreMongo");
|
|
||||||
} else {
|
|
||||||
isPhoenixNotebooks = isPhoenixFeatures = isPublicInternetAllowed;
|
|
||||||
}
|
}
|
||||||
} else {
|
},
|
||||||
isPhoenixNotebooks = isPhoenixFeatures = false;
|
initializeGitHubRepos: (pinnedRepos: IPinnedRepo[]): void => {
|
||||||
}
|
const gitHubNotebooksContentRoot = cloneDeep(get().gitHubNotebooksContentRoot);
|
||||||
set({ isPhoenixNotebooks: isPhoenixNotebooks });
|
if (gitHubNotebooksContentRoot) {
|
||||||
set({ isPhoenixFeatures: isPhoenixFeatures });
|
gitHubNotebooksContentRoot.children = [];
|
||||||
}
|
pinnedRepos?.forEach((pinnedRepo) => {
|
||||||
},
|
const repoFullName = GitHubUtils.toRepoFullName(pinnedRepo.owner, pinnedRepo.name);
|
||||||
setIsPhoenixNotebooks: (isPhoenixNotebooks: boolean) => set({ isPhoenixNotebooks: isPhoenixNotebooks }),
|
const repoTreeItem: NotebookContentItem = {
|
||||||
setIsPhoenixFeatures: (isPhoenixFeatures: boolean) => set({ isPhoenixFeatures: isPhoenixFeatures }),
|
name: repoFullName,
|
||||||
}));
|
path: "PsuedoDir",
|
||||||
|
type: NotebookContentItemType.Directory,
|
||||||
|
children: [],
|
||||||
|
parent: gitHubNotebooksContentRoot,
|
||||||
|
};
|
||||||
|
|
||||||
|
pinnedRepo.branches.forEach((branch) => {
|
||||||
|
repoTreeItem.children.push({
|
||||||
|
name: branch.name,
|
||||||
|
path: GitHubUtils.toContentUri(pinnedRepo.owner, pinnedRepo.name, branch.name, ""),
|
||||||
|
type: NotebookContentItemType.Directory,
|
||||||
|
parent: repoTreeItem,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
gitHubNotebooksContentRoot.children.push(repoTreeItem);
|
||||||
|
});
|
||||||
|
|
||||||
|
set({ gitHubNotebooksContentRoot });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setConnectionInfo: (connectionInfo: ContainerConnectionInfo) => set({ connectionInfo }),
|
||||||
|
setIsAllocating: (isAllocating: boolean) => set({ isAllocating }),
|
||||||
|
resetContainerConnection: (connectionStatus: ContainerConnectionInfo): void => {
|
||||||
|
useTabs.getState().closeAllNotebookTabs(true);
|
||||||
|
useNotebook.getState().setConnectionInfo(connectionStatus);
|
||||||
|
useNotebook.getState().setNotebookServerInfo(undefined);
|
||||||
|
useNotebook.getState().setIsAllocating(false);
|
||||||
|
useNotebook.getState().setContainerStatus({
|
||||||
|
status: undefined,
|
||||||
|
durationLeftInMinutes: undefined,
|
||||||
|
phoenixServerInfo: undefined,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setIsRefreshed: (isRefreshed: boolean) => set({ isRefreshed }),
|
||||||
|
setContainerStatus: (containerStatus: ContainerInfo) => set({ containerStatus }),
|
||||||
|
getPhoenixStatus: async () => {
|
||||||
|
if (get().isPhoenixNotebooks === undefined || get().isPhoenixFeatures === undefined) {
|
||||||
|
let isPhoenixNotebooks = false;
|
||||||
|
let isPhoenixFeatures = false;
|
||||||
|
|
||||||
|
const isPublicInternetAllowed = isPublicInternetAccessAllowed();
|
||||||
|
const phoenixClient = new PhoenixClient(userContext?.databaseAccount?.id);
|
||||||
|
const dbAccountAllowedInfo = await phoenixClient.getDbAccountAllowedStatus();
|
||||||
|
|
||||||
|
if (dbAccountAllowedInfo.status === HttpStatusCodes.OK) {
|
||||||
|
if (dbAccountAllowedInfo?.type === PhoenixErrorType.PhoenixFlightFallback) {
|
||||||
|
isPhoenixNotebooks = isPublicInternetAllowed && userContext.features.phoenixNotebooks === true;
|
||||||
|
isPhoenixFeatures =
|
||||||
|
isPublicInternetAllowed &&
|
||||||
|
// phoenix needs to be enabled for Postgres and VCoreMongo accounts since the PSQL and mongo shell requires phoenix containers
|
||||||
|
(userContext.features.phoenixFeatures === true ||
|
||||||
|
userContext.apiType === "Postgres" ||
|
||||||
|
userContext.apiType === "VCoreMongo");
|
||||||
|
} else {
|
||||||
|
isPhoenixNotebooks = isPhoenixFeatures = isPublicInternetAllowed;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isPhoenixNotebooks = isPhoenixFeatures = false;
|
||||||
|
}
|
||||||
|
set({ isPhoenixNotebooks: isPhoenixNotebooks });
|
||||||
|
set({ isPhoenixFeatures: isPhoenixFeatures });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setIsPhoenixNotebooks: (isPhoenixNotebooks: boolean) => set({ isPhoenixNotebooks: isPhoenixNotebooks }),
|
||||||
|
setIsPhoenixFeatures: (isPhoenixFeatures: boolean) => set({ isPhoenixFeatures: isPhoenixFeatures }),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
@ -51,7 +51,7 @@ import { useClientWriteEnabled } from "hooks/useClientWriteEnabled";
|
|||||||
import { useQueryCopilot } from "hooks/useQueryCopilot";
|
import { useQueryCopilot } from "hooks/useQueryCopilot";
|
||||||
import { useSidePanel } from "hooks/useSidePanel";
|
import { useSidePanel } from "hooks/useSidePanel";
|
||||||
import React, { FunctionComponent, useState } from "react";
|
import React, { FunctionComponent, useState } from "react";
|
||||||
import create, { UseStore } from "zustand";
|
import { create } from "zustand";
|
||||||
import Explorer from "../../Explorer";
|
import Explorer from "../../Explorer";
|
||||||
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";
|
import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm";
|
||||||
|
|
||||||
@ -65,8 +65,6 @@ export interface DataPlaneRbacState {
|
|||||||
setAadDataPlaneUpdated: (aadTokenUpdated: boolean) => void;
|
setAadDataPlaneUpdated: (aadTokenUpdated: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
type DataPlaneRbacStore = UseStore<Partial<DataPlaneRbacState>>;
|
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles({
|
||||||
bulletList: {
|
bulletList: {
|
||||||
listStyleType: "disc",
|
listStyleType: "disc",
|
||||||
@ -100,7 +98,7 @@ const useStyles = makeStyles({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const useDataPlaneRbac: DataPlaneRbacStore = create(() => ({
|
export const useDataPlaneRbac = create<Partial<DataPlaneRbacState>>(() => ({
|
||||||
dataPlaneRbacEnabled: false,
|
dataPlaneRbacEnabled: false,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import { MinimalQueryIterator } from "Common/IteratorUtilities";
|
import { MinimalQueryIterator } from "Common/IteratorUtilities";
|
||||||
import QueryError from "Common/QueryError";
|
import QueryError from "Common/QueryError";
|
||||||
|
import * as DataModels from "Contracts/DataModels";
|
||||||
import { QueryResults } from "Contracts/ViewModels";
|
import { QueryResults } from "Contracts/ViewModels";
|
||||||
import { CopilotMessage } from "Explorer/QueryCopilot/Shared/QueryCopilotInterfaces";
|
import { CopilotMessage } from "Explorer/QueryCopilot/Shared/QueryCopilotInterfaces";
|
||||||
import { guid } from "Explorer/Tables/Utilities";
|
import { guid } from "Explorer/Tables/Utilities";
|
||||||
import { QueryCopilotState } from "hooks/useQueryCopilot";
|
import { QueryCopilotState } from "hooks/useQueryCopilot";
|
||||||
|
|
||||||
import React, { createContext, useContext, useState } from "react";
|
import React, { createContext, useContext, useState } from "react";
|
||||||
import create from "zustand";
|
import { create } from "zustand";
|
||||||
|
|
||||||
const context = createContext(null);
|
const context = createContext(null);
|
||||||
const useCopilotStore = (): Partial<QueryCopilotState> => useContext(context);
|
const useCopilotStore = (): Partial<QueryCopilotState> => useContext(context);
|
||||||
|
|
||||||
@ -24,12 +26,12 @@ const CopilotProvider = ({ children }: { children: React.ReactNode }): JSX.Eleme
|
|||||||
isGeneratingQuery: false,
|
isGeneratingQuery: false,
|
||||||
isGeneratingExplanation: false,
|
isGeneratingExplanation: false,
|
||||||
isExecuting: false,
|
isExecuting: false,
|
||||||
dislikeQuery: undefined,
|
dislikeQuery: undefined as boolean,
|
||||||
showCallout: false,
|
showCallout: false,
|
||||||
showSamplePrompts: false,
|
showSamplePrompts: false,
|
||||||
queryIterator: undefined,
|
queryIterator: undefined as MinimalQueryIterator,
|
||||||
queryResults: undefined,
|
queryResults: undefined as QueryResults,
|
||||||
errors: [],
|
errors: [] as QueryError[],
|
||||||
isSamplePromptsOpen: false,
|
isSamplePromptsOpen: false,
|
||||||
showPromptTeachingBubble: true,
|
showPromptTeachingBubble: true,
|
||||||
showDeletePopup: false,
|
showDeletePopup: false,
|
||||||
@ -41,7 +43,7 @@ const CopilotProvider = ({ children }: { children: React.ReactNode }): JSX.Eleme
|
|||||||
wasCopilotUsed: false,
|
wasCopilotUsed: false,
|
||||||
showWelcomeSidebar: true,
|
showWelcomeSidebar: true,
|
||||||
showCopilotSidebar: false,
|
showCopilotSidebar: false,
|
||||||
chatMessages: [],
|
chatMessages: [] as CopilotMessage[],
|
||||||
shouldIncludeInMessages: true,
|
shouldIncludeInMessages: true,
|
||||||
showExplanationBubble: false,
|
showExplanationBubble: false,
|
||||||
isAllocatingContainer: false,
|
isAllocatingContainer: false,
|
||||||
@ -86,7 +88,7 @@ const CopilotProvider = ({ children }: { children: React.ReactNode }): JSX.Eleme
|
|||||||
},
|
},
|
||||||
|
|
||||||
resetQueryCopilotStates: () => {
|
resetQueryCopilotStates: () => {
|
||||||
set((state) => ({
|
set((state: QueryCopilotState) => ({
|
||||||
...state,
|
...state,
|
||||||
generatedQuery: "",
|
generatedQuery: "",
|
||||||
likeQuery: false,
|
likeQuery: false,
|
||||||
@ -99,11 +101,11 @@ const CopilotProvider = ({ children }: { children: React.ReactNode }): JSX.Eleme
|
|||||||
isGeneratingQuery: false,
|
isGeneratingQuery: false,
|
||||||
isGeneratingExplanation: false,
|
isGeneratingExplanation: false,
|
||||||
isExecuting: false,
|
isExecuting: false,
|
||||||
dislikeQuery: undefined,
|
dislikeQuery: undefined as boolean,
|
||||||
showCallout: false,
|
showCallout: false,
|
||||||
showSamplePrompts: false,
|
showSamplePrompts: false,
|
||||||
queryIterator: undefined,
|
queryIterator: undefined as MinimalQueryIterator,
|
||||||
queryResults: undefined,
|
queryResults: undefined as QueryResults,
|
||||||
errorMessage: "",
|
errorMessage: "",
|
||||||
isSamplePromptsOpen: false,
|
isSamplePromptsOpen: false,
|
||||||
showPromptTeachingBubble: true,
|
showPromptTeachingBubble: true,
|
||||||
@ -115,19 +117,19 @@ const CopilotProvider = ({ children }: { children: React.ReactNode }): JSX.Eleme
|
|||||||
generatedQueryComments: "",
|
generatedQueryComments: "",
|
||||||
wasCopilotUsed: false,
|
wasCopilotUsed: false,
|
||||||
showCopilotSidebar: false,
|
showCopilotSidebar: false,
|
||||||
chatMessages: [],
|
chatMessages: [] as CopilotMessage[],
|
||||||
shouldIncludeInMessages: true,
|
shouldIncludeInMessages: true,
|
||||||
showExplanationBubble: false,
|
showExplanationBubble: false,
|
||||||
notebookServerInfo: {
|
notebookServerInfo: {
|
||||||
notebookServerEndpoint: undefined,
|
notebookServerEndpoint: undefined,
|
||||||
authToken: undefined,
|
authToken: undefined,
|
||||||
forwardingId: undefined,
|
forwardingId: undefined,
|
||||||
},
|
} as DataModels.NotebookWorkspaceConnectionInfo,
|
||||||
containerStatus: {
|
containerStatus: {
|
||||||
status: undefined,
|
status: undefined,
|
||||||
durationLeftInMinutes: undefined,
|
durationLeftInMinutes: undefined,
|
||||||
phoenixServerInfo: undefined,
|
phoenixServerInfo: undefined,
|
||||||
},
|
} as DataModels.ContainerInfo,
|
||||||
isAllocatingContainer: false,
|
isAllocatingContainer: false,
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
@ -137,3 +139,4 @@ const CopilotProvider = ({ children }: { children: React.ReactNode }): JSX.Eleme
|
|||||||
};
|
};
|
||||||
|
|
||||||
export { CopilotProvider, useCopilotStore };
|
export { CopilotProvider, useCopilotStore };
|
||||||
|
|
||||||
|
@ -77,39 +77,39 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
|
|||||||
this.subscriptions.push(
|
this.subscriptions.push(
|
||||||
{
|
{
|
||||||
dispose: useNotebook.subscribe(
|
dispose: useNotebook.subscribe(
|
||||||
() => this.setState({}),
|
|
||||||
(state) => state.isNotebookEnabled,
|
(state) => state.isNotebookEnabled,
|
||||||
|
() => this.setState({}),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{ dispose: useSelectedNode.subscribe(() => this.setState({})) },
|
{ dispose: useSelectedNode.subscribe(() => this.setState({})) },
|
||||||
{
|
{
|
||||||
dispose: useCarousel.subscribe(
|
dispose: useCarousel.subscribe(
|
||||||
() => this.setState({}),
|
|
||||||
(state) => state.showCoachMark,
|
(state) => state.showCoachMark,
|
||||||
|
() => this.setState({}),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dispose: usePostgres.subscribe(
|
dispose: usePostgres.subscribe(
|
||||||
() => this.setState({}),
|
|
||||||
(state) => state.showPostgreTeachingBubble,
|
(state) => state.showPostgreTeachingBubble,
|
||||||
|
() => this.setState({}),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dispose: usePostgres.subscribe(
|
dispose: usePostgres.subscribe(
|
||||||
() => this.setState({}),
|
|
||||||
(state) => state.showResetPasswordBubble,
|
(state) => state.showResetPasswordBubble,
|
||||||
|
() => this.setState({}),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dispose: useDatabases.subscribe(
|
dispose: useDatabases.subscribe(
|
||||||
() => this.setState({}),
|
|
||||||
(state) => state.sampleDataResourceTokenCollection,
|
(state) => state.sampleDataResourceTokenCollection,
|
||||||
|
() => this.setState({}),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dispose: useQueryCopilot.subscribe(
|
dispose: useQueryCopilot.subscribe(
|
||||||
() => this.setState({}),
|
|
||||||
(state) => state.copilotEnabled,
|
(state) => state.copilotEnabled,
|
||||||
|
() => this.setState({}),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { FitAddon } from "@xterm/addon-fit";
|
import { FitAddon } from "@xterm/addon-fit";
|
||||||
import { Terminal } from "@xterm/xterm";
|
import { Terminal } from "@xterm/xterm";
|
||||||
|
import "@xterm/xterm/css/xterm.css";
|
||||||
import React, { useEffect, useRef } from "react";
|
import React, { useEffect, useRef } from "react";
|
||||||
import "xterm/css/xterm.css";
|
|
||||||
import { DatabaseAccount } from "../../../Contracts/DataModels";
|
import { DatabaseAccount } from "../../../Contracts/DataModels";
|
||||||
import { TerminalKind } from "../../../Contracts/ViewModels";
|
import { TerminalKind } from "../../../Contracts/ViewModels";
|
||||||
import { startCloudShellTerminal } from "./CloudShellTerminalCore";
|
import { startCloudShellTerminal } from "./CloudShellTerminalCore";
|
||||||
|
@ -44,8 +44,8 @@ export default class NotebookTabV2 extends NotebookTabBase {
|
|||||||
this.container = options.container;
|
this.container = options.container;
|
||||||
this.notebookPath = ko.observable(options.notebookContentItem.path);
|
this.notebookPath = ko.observable(options.notebookContentItem.path);
|
||||||
useNotebook.subscribe(
|
useNotebook.subscribe(
|
||||||
() => logConsoleInfo("New notebook server info received."),
|
|
||||||
(state) => state.notebookServerInfo,
|
(state) => state.notebookServerInfo,
|
||||||
|
() => logConsoleInfo("New notebook server info received."),
|
||||||
);
|
);
|
||||||
this.notebookComponentAdapter = new NotebookComponentAdapter({
|
this.notebookComponentAdapter = new NotebookComponentAdapter({
|
||||||
contentItem: options.notebookContentItem,
|
contentItem: options.notebookContentItem,
|
||||||
@ -165,7 +165,7 @@ export default class NotebookTabV2 extends NotebookTabBase {
|
|||||||
{
|
{
|
||||||
iconSrc: null,
|
iconSrc: null,
|
||||||
iconAlt: kernelLabel,
|
iconAlt: kernelLabel,
|
||||||
onCommandClick: () => {},
|
onCommandClick: () => { },
|
||||||
commandButtonLabel: null,
|
commandButtonLabel: null,
|
||||||
hasPopup: false,
|
hasPopup: false,
|
||||||
disabled: availableKernels.length < 1,
|
disabled: availableKernels.length < 1,
|
||||||
@ -276,7 +276,7 @@ export default class NotebookTabV2 extends NotebookTabBase {
|
|||||||
{
|
{
|
||||||
iconSrc: null,
|
iconSrc: null,
|
||||||
iconAlt: null,
|
iconAlt: null,
|
||||||
onCommandClick: () => {},
|
onCommandClick: () => { },
|
||||||
commandButtonLabel: null,
|
commandButtonLabel: null,
|
||||||
ariaLabel: cellTypeLabel,
|
ariaLabel: cellTypeLabel,
|
||||||
hasPopup: false,
|
hasPopup: false,
|
||||||
|
@ -16,7 +16,6 @@ import { useQueryCopilot } from "hooks/useQueryCopilot";
|
|||||||
import { ReactTabKind, useTabs } from "hooks/useTabs";
|
import { ReactTabKind, useTabs } from "hooks/useTabs";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { useEffect, useMemo } from "react";
|
import { useEffect, useMemo } from "react";
|
||||||
import shallow from "zustand/shallow";
|
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
import { useNotebook } from "../Notebook/useNotebook";
|
import { useNotebook } from "../Notebook/useNotebook";
|
||||||
|
|
||||||
@ -38,13 +37,8 @@ export const ResourceTree: React.FC<ResourceTreeProps> = ({ explorer }: Resource
|
|||||||
const [openItems, setOpenItems] = React.useState<TreeItemValue[]>([]);
|
const [openItems, setOpenItems] = React.useState<TreeItemValue[]>([]);
|
||||||
const treeStyles = useTreeStyles();
|
const treeStyles = useTreeStyles();
|
||||||
|
|
||||||
const { isNotebookEnabled } = useNotebook(
|
const isNotebookEnabled = useNotebook((state) => state.isNotebookEnabled)
|
||||||
(state) => ({
|
|
||||||
isNotebookEnabled: state.isNotebookEnabled,
|
|
||||||
}),
|
|
||||||
shallow,
|
|
||||||
);
|
|
||||||
|
|
||||||
// We intentionally avoid using a state selector here because we want to re-render the tree if the active tab changes.
|
// We intentionally avoid using a state selector here because we want to re-render the tree if the active tab changes.
|
||||||
const { refreshActiveTab } = useTabs();
|
const { refreshActiveTab } = useTabs();
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@ import PublishIcon from "../../../images/notebook/publish_content.svg";
|
|||||||
import RefreshIcon from "../../../images/refresh-cosmos.svg";
|
import RefreshIcon from "../../../images/refresh-cosmos.svg";
|
||||||
import CollectionIcon from "../../../images/tree-collection.svg";
|
import CollectionIcon from "../../../images/tree-collection.svg";
|
||||||
import { ReactAdapter } from "../../Bindings/ReactBindingHandler";
|
import { ReactAdapter } from "../../Bindings/ReactBindingHandler";
|
||||||
import { isPublicInternetAccessAllowed } from "../../Common/DatabaseAccountUtility";
|
|
||||||
import * as DataModels from "../../Contracts/DataModels";
|
import * as DataModels from "../../Contracts/DataModels";
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
import * as ViewModels from "../../Contracts/ViewModels";
|
||||||
import { IPinnedRepo } from "../../Juno/JunoClient";
|
import { IPinnedRepo } from "../../Juno/JunoClient";
|
||||||
@ -58,12 +57,12 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
|||||||
|
|
||||||
useSelectedNode.subscribe(() => this.triggerRender());
|
useSelectedNode.subscribe(() => this.triggerRender());
|
||||||
useTabs.subscribe(
|
useTabs.subscribe(
|
||||||
() => this.triggerRender(),
|
|
||||||
(state) => state.activeTab,
|
(state) => state.activeTab,
|
||||||
|
() => this.triggerRender(),
|
||||||
);
|
);
|
||||||
useNotebook.subscribe(
|
useNotebook.subscribe(
|
||||||
() => this.triggerRender(),
|
|
||||||
(state) => state.isNotebookEnabled,
|
(state) => state.isNotebookEnabled,
|
||||||
|
() => this.triggerRender(),
|
||||||
);
|
);
|
||||||
|
|
||||||
useDatabases.subscribe(() => this.triggerRender());
|
useDatabases.subscribe(() => this.triggerRender());
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import _ from "underscore";
|
import _ from "underscore";
|
||||||
import create, { UseStore } from "zustand";
|
import { create } from "zustand";
|
||||||
|
import { subscribeWithSelector } from "zustand/middleware";
|
||||||
import * as Constants from "../Common/Constants";
|
import * as Constants from "../Common/Constants";
|
||||||
import * as ViewModels from "../Contracts/ViewModels";
|
import * as ViewModels from "../Contracts/ViewModels";
|
||||||
import { userContext } from "../UserContext";
|
import { userContext } from "../UserContext";
|
||||||
@ -26,143 +27,147 @@ interface DatabasesState {
|
|||||||
validateCollectionId: (databaseId: string, collectionId: string) => Promise<boolean>;
|
validateCollectionId: (databaseId: string, collectionId: string) => Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useDatabases: UseStore<DatabasesState> = create((set, get) => ({
|
export const useDatabases = create<DatabasesState>()(
|
||||||
databases: [],
|
subscribeWithSelector(
|
||||||
resourceTokenCollection: undefined,
|
(set, get) => ({
|
||||||
sampleDataResourceTokenCollection: undefined,
|
databases: [] as ViewModels.Database[],
|
||||||
updateDatabase: (updatedDatabase: ViewModels.Database) =>
|
resourceTokenCollection: undefined as ViewModels.CollectionBase,
|
||||||
set((state) => {
|
sampleDataResourceTokenCollection: undefined as ViewModels.CollectionBase,
|
||||||
const updatedDatabases = state.databases.map((database: ViewModels.Database) => {
|
updateDatabase: (updatedDatabase: ViewModels.Database) =>
|
||||||
if (database?.id() === updatedDatabase?.id()) {
|
set((state) => {
|
||||||
return updatedDatabase;
|
const updatedDatabases = state.databases.map((database: ViewModels.Database) => {
|
||||||
|
if (database?.id() === updatedDatabase?.id()) {
|
||||||
|
return updatedDatabase;
|
||||||
|
}
|
||||||
|
|
||||||
|
return database;
|
||||||
|
});
|
||||||
|
return { databases: updatedDatabases };
|
||||||
|
}),
|
||||||
|
addDatabases: (databases: ViewModels.Database[]) =>
|
||||||
|
set((state) => ({
|
||||||
|
databases: [...state.databases, ...databases].sort((db1, db2) => db1.id().localeCompare(db2.id())),
|
||||||
|
})),
|
||||||
|
deleteDatabase: (database: ViewModels.Database) =>
|
||||||
|
set((state) => ({ databases: state.databases.filter((db) => database.id() !== db.id()) })),
|
||||||
|
clearDatabases: () => set(() => ({ databases: [] })),
|
||||||
|
isSaveQueryEnabled: () => {
|
||||||
|
const savedQueriesDatabase: ViewModels.Database = _.find(
|
||||||
|
get().databases,
|
||||||
|
(database: ViewModels.Database) => database.id() === Constants.SavedQueries.DatabaseName,
|
||||||
|
);
|
||||||
|
if (!savedQueriesDatabase) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const savedQueriesCollection: ViewModels.Collection =
|
||||||
|
savedQueriesDatabase &&
|
||||||
|
_.find(
|
||||||
|
savedQueriesDatabase.collections(),
|
||||||
|
(collection: ViewModels.Collection) => collection.id() === Constants.SavedQueries.CollectionName,
|
||||||
|
);
|
||||||
|
if (!savedQueriesCollection) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
findDatabaseWithId: (databaseId: string, isSampleDatabase?: boolean) => {
|
||||||
|
return isSampleDatabase === undefined
|
||||||
|
? get().databases.find((db) => databaseId === db.id())
|
||||||
|
: get().databases.find((db) => databaseId === db.id() && db.isSampleDB === isSampleDatabase);
|
||||||
|
},
|
||||||
|
isLastNonEmptyDatabase: () => {
|
||||||
|
const databases = get().databases;
|
||||||
|
return databases.length === 1 && (databases[0].collections()?.length > 0 || !!databases[0].offer());
|
||||||
|
},
|
||||||
|
findCollection: (databaseId: string, collectionId: string) => {
|
||||||
|
const database = get().findDatabaseWithId(databaseId);
|
||||||
|
return database?.collections()?.find((collection) => collection.id() === collectionId);
|
||||||
|
},
|
||||||
|
isLastCollection: () => {
|
||||||
|
const databases = get().databases;
|
||||||
|
if (databases.length === 0) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return database;
|
let collectionCount = 0;
|
||||||
});
|
for (let i = 0; i < databases.length; i++) {
|
||||||
return { databases: updatedDatabases };
|
const database = databases[i];
|
||||||
}),
|
collectionCount += database.collections().length;
|
||||||
addDatabases: (databases: ViewModels.Database[]) =>
|
if (collectionCount > 1) {
|
||||||
set((state) => ({
|
return false;
|
||||||
databases: [...state.databases, ...databases].sort((db1, db2) => db1.id().localeCompare(db2.id())),
|
}
|
||||||
})),
|
}
|
||||||
deleteDatabase: (database: ViewModels.Database) =>
|
|
||||||
set((state) => ({ databases: state.databases.filter((db) => database.id() !== db.id()) })),
|
|
||||||
clearDatabases: () => set(() => ({ databases: [] })),
|
|
||||||
isSaveQueryEnabled: () => {
|
|
||||||
const savedQueriesDatabase: ViewModels.Database = _.find(
|
|
||||||
get().databases,
|
|
||||||
(database: ViewModels.Database) => database.id() === Constants.SavedQueries.DatabaseName,
|
|
||||||
);
|
|
||||||
if (!savedQueriesDatabase) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const savedQueriesCollection: ViewModels.Collection =
|
|
||||||
savedQueriesDatabase &&
|
|
||||||
_.find(
|
|
||||||
savedQueriesDatabase.collections(),
|
|
||||||
(collection: ViewModels.Collection) => collection.id() === Constants.SavedQueries.CollectionName,
|
|
||||||
);
|
|
||||||
if (!savedQueriesCollection) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
findDatabaseWithId: (databaseId: string, isSampleDatabase?: boolean) => {
|
|
||||||
return isSampleDatabase === undefined
|
|
||||||
? get().databases.find((db) => databaseId === db.id())
|
|
||||||
: get().databases.find((db) => databaseId === db.id() && db.isSampleDB === isSampleDatabase);
|
|
||||||
},
|
|
||||||
isLastNonEmptyDatabase: () => {
|
|
||||||
const databases = get().databases;
|
|
||||||
return databases.length === 1 && (databases[0].collections()?.length > 0 || !!databases[0].offer());
|
|
||||||
},
|
|
||||||
findCollection: (databaseId: string, collectionId: string) => {
|
|
||||||
const database = get().findDatabaseWithId(databaseId);
|
|
||||||
return database?.collections()?.find((collection) => collection.id() === collectionId);
|
|
||||||
},
|
|
||||||
isLastCollection: () => {
|
|
||||||
const databases = get().databases;
|
|
||||||
if (databases.length === 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let collectionCount = 0;
|
return true;
|
||||||
for (let i = 0; i < databases.length; i++) {
|
},
|
||||||
const database = databases[i];
|
loadDatabaseOffers: async () => {
|
||||||
collectionCount += database.collections().length;
|
|
||||||
if (collectionCount > 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
loadDatabaseOffers: async () => {
|
|
||||||
await Promise.all(
|
|
||||||
get().databases?.map(async (database: ViewModels.Database) => {
|
|
||||||
await database.loadOffer();
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
loadAllOffers: async () => {
|
|
||||||
await Promise.all(
|
|
||||||
get().databases?.map(async (database: ViewModels.Database) => {
|
|
||||||
await database.loadOffer();
|
|
||||||
await database.loadCollections();
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
(database.collections() || []).map(async (collection: ViewModels.Collection) => {
|
get().databases?.map(async (database: ViewModels.Database) => {
|
||||||
await collection.loadOffer();
|
await database.loadOffer();
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}),
|
},
|
||||||
);
|
loadAllOffers: async () => {
|
||||||
},
|
await Promise.all(
|
||||||
isFirstResourceCreated: () => {
|
get().databases?.map(async (database: ViewModels.Database) => {
|
||||||
const databases = get().databases;
|
await database.loadOffer();
|
||||||
|
await database.loadCollections();
|
||||||
|
await Promise.all(
|
||||||
|
(database.collections() || []).map(async (collection: ViewModels.Collection) => {
|
||||||
|
await collection.loadOffer();
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
isFirstResourceCreated: () => {
|
||||||
|
const databases = get().databases;
|
||||||
|
|
||||||
if (!databases || databases.length === 0) {
|
if (!databases || databases.length === 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return databases.some((database) => {
|
return databases.some((database) => {
|
||||||
// user has created at least one collection
|
// user has created at least one collection
|
||||||
if (database.collections()?.length > 0) {
|
if (database.collections()?.length > 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// user has created a database with shared throughput
|
// user has created a database with shared throughput
|
||||||
if (database.offer()) {
|
if (database.offer()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// use has created an empty database without shared throughput
|
// use has created an empty database without shared throughput
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
findSelectedDatabase: (): ViewModels.Database => {
|
findSelectedDatabase: (): ViewModels.Database => {
|
||||||
const selectedNode = useSelectedNode.getState().selectedNode;
|
const selectedNode = useSelectedNode.getState().selectedNode;
|
||||||
if (!selectedNode) {
|
if (!selectedNode) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
if (selectedNode.nodeKind === "Database") {
|
if (selectedNode.nodeKind === "Database") {
|
||||||
return _.find(get().databases, (database: ViewModels.Database) => database.id() === selectedNode.id());
|
return _.find(get().databases, (database: ViewModels.Database) => database.id() === selectedNode.id());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedNode.nodeKind === "Collection") {
|
if (selectedNode.nodeKind === "Collection") {
|
||||||
return selectedNode.database;
|
return selectedNode.database;
|
||||||
}
|
}
|
||||||
|
|
||||||
return selectedNode.collection?.database;
|
return selectedNode.collection?.database;
|
||||||
},
|
},
|
||||||
validateDatabaseId: (id: string): boolean => {
|
validateDatabaseId: (id: string): boolean => {
|
||||||
return !get().databases.some((database) => database.id() === id);
|
return !get().databases.some((database) => database.id() === id);
|
||||||
},
|
},
|
||||||
validateCollectionId: async (databaseId: string, collectionId: string): Promise<boolean> => {
|
validateCollectionId: async (databaseId: string, collectionId: string): Promise<boolean> => {
|
||||||
const database = get().databases.find((db) => db.id() === databaseId);
|
const database = get().databases.find((db) => db.id() === databaseId);
|
||||||
// For a new tables account, database is undefined when creating the first table
|
// For a new tables account, database is undefined when creating the first table
|
||||||
if (!database && userContext.apiType === "Tables") {
|
if (!database && userContext.apiType === "Tables") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
await database.loadCollections();
|
await database.loadCollections();
|
||||||
return !database.collections().some((collection) => collection.id() === collectionId);
|
return !database.collections().some((collection) => collection.id() === collectionId);
|
||||||
},
|
},
|
||||||
}));
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ConnectionStatusType, QueryCopilotSampleContainerId, QueryCopilotSampleDatabaseId } from "Common/Constants";
|
import { ConnectionStatusType, QueryCopilotSampleContainerId, QueryCopilotSampleDatabaseId } from "Common/Constants";
|
||||||
import { useNotebook } from "Explorer/Notebook/useNotebook";
|
import { useNotebook } from "Explorer/Notebook/useNotebook";
|
||||||
import create, { UseStore } from "zustand";
|
import { create } from "zustand";
|
||||||
import * as ViewModels from "../Contracts/ViewModels";
|
import * as ViewModels from "../Contracts/ViewModels";
|
||||||
import { useTabs } from "../hooks/useTabs";
|
import { useTabs } from "../hooks/useTabs";
|
||||||
export interface SelectedNodeState {
|
export interface SelectedNodeState {
|
||||||
@ -17,7 +17,7 @@ export interface SelectedNodeState {
|
|||||||
isQueryCopilotCollectionSelected: () => boolean;
|
isQueryCopilotCollectionSelected: () => boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useSelectedNode: UseStore<SelectedNodeState> = create((set, get) => ({
|
export const useSelectedNode = create<SelectedNodeState>((set, get) => ({
|
||||||
selectedNode: undefined,
|
selectedNode: undefined,
|
||||||
setSelectedNode: (node: ViewModels.TreeNode) => set({ selectedNode: node }),
|
setSelectedNode: (node: ViewModels.TreeNode) => set({ selectedNode: node }),
|
||||||
isDatabaseNodeOrNoneSelected: (): boolean => {
|
isDatabaseNodeOrNoneSelected: (): boolean => {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { PropsWithChildren, useEffect } from "react";
|
import { PropsWithChildren, useEffect } from "react";
|
||||||
import { KeyBindingMap, tinykeys } from "tinykeys";
|
import { KeyBindingMap, tinykeys } from "tinykeys";
|
||||||
import create, { UseStore } from "zustand";
|
import { create } from "zustand";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a keyboard shortcut handler.
|
* Represents a keyboard shortcut handler.
|
||||||
@ -126,7 +126,7 @@ export const clearKeyboardActionGroup = (group: KeyboardActionGroup) => {
|
|||||||
useKeyboardActionHandlers.getState().setHandlers(group, {});
|
useKeyboardActionHandlers.getState().setHandlers(group, {});
|
||||||
};
|
};
|
||||||
|
|
||||||
const useKeyboardActionHandlers: UseStore<KeyboardShortcutState> = create((set, get) => ({
|
const useKeyboardActionHandlers = create<KeyboardShortcutState>((set, get) => ({
|
||||||
allHandlers: {},
|
allHandlers: {},
|
||||||
groups: {},
|
groups: {},
|
||||||
setHandlers: (group: KeyboardActionGroup, handlers: KeyboardHandlerMap) => {
|
setHandlers: (group: KeyboardActionGroup, handlers: KeyboardHandlerMap) => {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import create, { UseStore } from "zustand";
|
import { create } from "zustand";
|
||||||
|
import { subscribeWithSelector } from "zustand/middleware";
|
||||||
|
|
||||||
interface CarouselState {
|
interface CarouselState {
|
||||||
shouldOpen: boolean;
|
shouldOpen: boolean;
|
||||||
@ -9,11 +10,15 @@ interface CarouselState {
|
|||||||
setShowCopilotCarousel: (showCopilotCarousel: boolean) => void;
|
setShowCopilotCarousel: (showCopilotCarousel: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useCarousel: UseStore<CarouselState> = create((set) => ({
|
export const useCarousel = create<CarouselState>()(
|
||||||
shouldOpen: false,
|
subscribeWithSelector(
|
||||||
showCoachMark: false,
|
(set) => ({
|
||||||
showCopilotCarousel: false,
|
shouldOpen: false,
|
||||||
setShouldOpen: (shouldOpen: boolean) => set({ shouldOpen }),
|
showCoachMark: false,
|
||||||
setShowCoachMark: (showCoachMark: boolean) => set({ showCoachMark }),
|
showCopilotCarousel: false,
|
||||||
setShowCopilotCarousel: (showCopilotCarousel: boolean) => set({ showCopilotCarousel }),
|
setShouldOpen: (shouldOpen: boolean) => set({ shouldOpen }),
|
||||||
}));
|
setShowCoachMark: (showCoachMark: boolean) => set({ showCoachMark }),
|
||||||
|
setShowCopilotCarousel: (showCopilotCarousel: boolean) => set({ showCopilotCarousel }),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import create, { UseStore } from "zustand";
|
import { create } from "zustand";
|
||||||
interface ClientWriteEnabledState {
|
interface ClientWriteEnabledState {
|
||||||
clientWriteEnabled: boolean;
|
clientWriteEnabled: boolean;
|
||||||
setClientWriteEnabled: (writeEnabled: boolean) => void;
|
setClientWriteEnabled: (writeEnabled: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useClientWriteEnabled: UseStore<ClientWriteEnabledState> = create((set) => ({
|
export const useClientWriteEnabled = create<ClientWriteEnabledState>((set) => ({
|
||||||
clientWriteEnabled: true,
|
clientWriteEnabled: true,
|
||||||
setClientWriteEnabled: (clientWriteEnabled: boolean) => set({ clientWriteEnabled }),
|
setClientWriteEnabled: (clientWriteEnabled: boolean) => set({ clientWriteEnabled }),
|
||||||
}));
|
}));
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { getDataTransferJobs } from "Common/dataAccess/dataTransfers";
|
import { getDataTransferJobs } from "Common/dataAccess/dataTransfers";
|
||||||
import { DataTransferJobGetResults } from "Utils/arm/generatedClients/dataTransferService/types";
|
import { DataTransferJobGetResults } from "Utils/arm/generatedClients/dataTransferService/types";
|
||||||
import create, { UseStore } from "zustand";
|
import { create } from "zustand";
|
||||||
|
|
||||||
export interface DataTransferJobsState {
|
export interface DataTransferJobsState {
|
||||||
dataTransferJobs: DataTransferJobGetResults[];
|
dataTransferJobs: DataTransferJobGetResults[];
|
||||||
@ -9,9 +9,7 @@ export interface DataTransferJobsState {
|
|||||||
setPollingDataTransferJobs: (pollingDataTransferJobs: Set<string>) => void;
|
setPollingDataTransferJobs: (pollingDataTransferJobs: Set<string>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
type DataTransferJobStore = UseStore<DataTransferJobsState>;
|
export const useDataTransferJobs = create<DataTransferJobsState>((set) => ({
|
||||||
|
|
||||||
export const useDataTransferJobs: DataTransferJobStore = create((set) => ({
|
|
||||||
dataTransferJobs: [],
|
dataTransferJobs: [],
|
||||||
pollingDataTransferJobs: new Set<string>(),
|
pollingDataTransferJobs: new Set<string>(),
|
||||||
setDataTransferJobs: (dataTransferJobs: DataTransferJobGetResults[]) => set({ dataTransferJobs }),
|
setDataTransferJobs: (dataTransferJobs: DataTransferJobGetResults[]) => set({ dataTransferJobs }),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import create, { UseStore } from "zustand";
|
import { create } from "zustand";
|
||||||
|
|
||||||
export interface NotebookSnapshotHooks {
|
export interface NotebookSnapshotHooks {
|
||||||
snapshot?: string;
|
snapshot?: string;
|
||||||
@ -7,7 +7,7 @@ export interface NotebookSnapshotHooks {
|
|||||||
setError: (error: string) => void;
|
setError: (error: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useNotebookSnapshotStore: UseStore<NotebookSnapshotHooks> = create((set) => ({
|
export const useNotebookSnapshotStore = create<NotebookSnapshotHooks>((set) => ({
|
||||||
snapshot: undefined,
|
snapshot: undefined,
|
||||||
error: undefined,
|
error: undefined,
|
||||||
setSnapshot: (imageSrc: string) => set((state) => ({ ...state, snapshot: imageSrc })),
|
setSnapshot: (imageSrc: string) => set((state) => ({ ...state, snapshot: imageSrc })),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import create, { UseStore } from "zustand";
|
import { create } from "zustand";
|
||||||
import { ConsoleData } from "../Explorer/Menus/NotificationConsole/ConsoleData";
|
import { ConsoleData } from "../Explorer/Menus/NotificationConsole/ConsoleData";
|
||||||
|
|
||||||
export interface NotificationConsoleState {
|
export interface NotificationConsoleState {
|
||||||
@ -15,7 +15,7 @@ export interface NotificationConsoleState {
|
|||||||
setConsoleAnimationFinished: (consoleAnimationFinished: boolean) => void;
|
setConsoleAnimationFinished: (consoleAnimationFinished: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useNotificationConsole: UseStore<NotificationConsoleState> = create((set) => ({
|
export const useNotificationConsole = create<NotificationConsoleState>((set) => ({
|
||||||
isExpanded: false,
|
isExpanded: false,
|
||||||
consoleData: undefined,
|
consoleData: undefined,
|
||||||
inProgressConsoleDataIdToBeDeleted: "",
|
inProgressConsoleDataIdToBeDeleted: "",
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import create, { UseStore } from "zustand";
|
import { create } from "zustand";
|
||||||
|
import { subscribeWithSelector } from "zustand/middleware";
|
||||||
|
|
||||||
interface TeachingBubbleState {
|
interface TeachingBubbleState {
|
||||||
showPostgreTeachingBubble: boolean;
|
showPostgreTeachingBubble: boolean;
|
||||||
@ -7,9 +8,13 @@ interface TeachingBubbleState {
|
|||||||
setShowResetPasswordBubble: (showResetPasswordBubble: boolean) => void;
|
setShowResetPasswordBubble: (showResetPasswordBubble: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const usePostgres: UseStore<TeachingBubbleState> = create((set) => ({
|
export const usePostgres = create<TeachingBubbleState>()(
|
||||||
showPostgreTeachingBubble: false,
|
subscribeWithSelector(
|
||||||
showResetPasswordBubble: false,
|
(set) => ({
|
||||||
setShowPostgreTeachingBubble: (showPostgreTeachingBubble: boolean) => set({ showPostgreTeachingBubble }),
|
showPostgreTeachingBubble: false,
|
||||||
setShowResetPasswordBubble: (showResetPasswordBubble: boolean) => set({ showResetPasswordBubble }),
|
showResetPasswordBubble: false,
|
||||||
}));
|
setShowPostgreTeachingBubble: (showPostgreTeachingBubble: boolean) => set({ showPostgreTeachingBubble }),
|
||||||
|
setShowResetPasswordBubble: (showResetPasswordBubble: boolean) => set({ showResetPasswordBubble }),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
@ -4,7 +4,8 @@ import { QueryResults } from "Contracts/ViewModels";
|
|||||||
import { CopilotMessage, CopilotSchemaAllocationInfo } from "Explorer/QueryCopilot/Shared/QueryCopilotInterfaces";
|
import { CopilotMessage, CopilotSchemaAllocationInfo } from "Explorer/QueryCopilot/Shared/QueryCopilotInterfaces";
|
||||||
import { guid } from "Explorer/Tables/Utilities";
|
import { guid } from "Explorer/Tables/Utilities";
|
||||||
import { useTabs } from "hooks/useTabs";
|
import { useTabs } from "hooks/useTabs";
|
||||||
import create, { UseStore } from "zustand";
|
import { create } from "zustand";
|
||||||
|
import { subscribeWithSelector } from "zustand/middleware";
|
||||||
import * as DataModels from "../Contracts/DataModels";
|
import * as DataModels from "../Contracts/DataModels";
|
||||||
import { ContainerInfo } from "../Contracts/DataModels";
|
import { ContainerInfo } from "../Contracts/DataModels";
|
||||||
|
|
||||||
@ -96,120 +97,12 @@ export interface QueryCopilotState {
|
|||||||
resetQueryCopilotStates: () => void;
|
resetQueryCopilotStates: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
type QueryCopilotStore = UseStore<Partial<QueryCopilotState>>;
|
export const useQueryCopilot = create<Partial<QueryCopilotState>>()(
|
||||||
|
subscribeWithSelector(
|
||||||
export const useQueryCopilot: QueryCopilotStore = create((set) => ({
|
(set) => ({
|
||||||
copilotEnabled: false,
|
copilotEnabled: false,
|
||||||
copilotUserDBEnabled: false,
|
copilotUserDBEnabled: false,
|
||||||
copilotSampleDBEnabled: false,
|
copilotSampleDBEnabled: false,
|
||||||
generatedQuery: "",
|
|
||||||
likeQuery: false,
|
|
||||||
userPrompt: "",
|
|
||||||
showFeedbackModal: false,
|
|
||||||
hideFeedbackModalForLikedQueries: false,
|
|
||||||
correlationId: "",
|
|
||||||
query: "SELECT * FROM c",
|
|
||||||
selectedQuery: "",
|
|
||||||
isGeneratingQuery: null,
|
|
||||||
isGeneratingExplanation: false,
|
|
||||||
isExecuting: false,
|
|
||||||
dislikeQuery: undefined,
|
|
||||||
showCallout: false,
|
|
||||||
showSamplePrompts: false,
|
|
||||||
queryIterator: undefined,
|
|
||||||
queryResults: undefined,
|
|
||||||
errors: [],
|
|
||||||
isSamplePromptsOpen: false,
|
|
||||||
showDeletePopup: false,
|
|
||||||
showFeedbackBar: false,
|
|
||||||
showCopyPopup: false,
|
|
||||||
showErrorMessageBar: false,
|
|
||||||
showInvalidQueryMessageBar: false,
|
|
||||||
generatedQueryComments: "",
|
|
||||||
wasCopilotUsed: false,
|
|
||||||
showWelcomeSidebar: true,
|
|
||||||
showCopilotSidebar: false,
|
|
||||||
chatMessages: [],
|
|
||||||
shouldIncludeInMessages: true,
|
|
||||||
showExplanationBubble: false,
|
|
||||||
notebookServerInfo: {
|
|
||||||
notebookServerEndpoint: undefined,
|
|
||||||
authToken: undefined,
|
|
||||||
forwardingId: undefined,
|
|
||||||
},
|
|
||||||
containerStatus: {
|
|
||||||
status: undefined,
|
|
||||||
durationLeftInMinutes: undefined,
|
|
||||||
phoenixServerInfo: undefined,
|
|
||||||
},
|
|
||||||
schemaAllocationInfo: {
|
|
||||||
databaseId: undefined,
|
|
||||||
containerId: undefined,
|
|
||||||
},
|
|
||||||
isAllocatingContainer: false,
|
|
||||||
copilotEnabledforExecution: false,
|
|
||||||
|
|
||||||
setCopilotEnabled: (copilotEnabled: boolean) => set({ copilotEnabled }),
|
|
||||||
setCopilotUserDBEnabled: (copilotUserDBEnabled: boolean) => set({ copilotUserDBEnabled }),
|
|
||||||
setCopilotSampleDBEnabled: (copilotSampleDBEnabled: boolean) => set({ copilotSampleDBEnabled }),
|
|
||||||
openFeedbackModal: (generatedQuery: string, likeQuery: boolean, userPrompt: string) =>
|
|
||||||
set({ generatedQuery, likeQuery, userPrompt, showFeedbackModal: true }),
|
|
||||||
closeFeedbackModal: () => set({ showFeedbackModal: false }),
|
|
||||||
setHideFeedbackModalForLikedQueries: (hideFeedbackModalForLikedQueries: boolean) =>
|
|
||||||
set({ hideFeedbackModalForLikedQueries }),
|
|
||||||
refreshCorrelationId: () => set({ correlationId: guid() }),
|
|
||||||
setUserPrompt: (userPrompt: string) => set({ userPrompt }),
|
|
||||||
setQuery: (query: string) => set({ query }),
|
|
||||||
setGeneratedQuery: (generatedQuery: string) => set({ generatedQuery }),
|
|
||||||
setSelectedQuery: (selectedQuery: string) => set({ selectedQuery }),
|
|
||||||
setIsGeneratingQuery: (isGeneratingQuery: boolean) => set({ isGeneratingQuery }),
|
|
||||||
setIsGeneratingExplanation: (isGeneratingExplanation: boolean) => set({ isGeneratingExplanation }),
|
|
||||||
setIsExecuting: (isExecuting: boolean) => set({ isExecuting }),
|
|
||||||
setLikeQuery: (likeQuery: boolean) => set({ likeQuery }),
|
|
||||||
setDislikeQuery: (dislikeQuery: boolean | undefined) => set({ dislikeQuery }),
|
|
||||||
setShowCallout: (showCallout: boolean) => set({ showCallout }),
|
|
||||||
setShowSamplePrompts: (showSamplePrompts: boolean) => set({ showSamplePrompts }),
|
|
||||||
setQueryIterator: (queryIterator: MinimalQueryIterator | undefined) => set({ queryIterator }),
|
|
||||||
setQueryResults: (queryResults: QueryResults | undefined) => set({ queryResults }),
|
|
||||||
setErrors: (errors: QueryError[]) => set({ errors }),
|
|
||||||
setIsSamplePromptsOpen: (isSamplePromptsOpen: boolean) => set({ isSamplePromptsOpen }),
|
|
||||||
setShowDeletePopup: (showDeletePopup: boolean) => set({ showDeletePopup }),
|
|
||||||
setShowFeedbackBar: (showFeedbackBar: boolean) => set({ showFeedbackBar }),
|
|
||||||
setshowCopyPopup: (showCopyPopup: boolean) => set({ showCopyPopup }),
|
|
||||||
setShowErrorMessageBar: (showErrorMessageBar: boolean) => set({ showErrorMessageBar }),
|
|
||||||
setShowInvalidQueryMessageBar: (showInvalidQueryMessageBar: boolean) => set({ showInvalidQueryMessageBar }),
|
|
||||||
setGeneratedQueryComments: (generatedQueryComments: string) => set({ generatedQueryComments }),
|
|
||||||
setWasCopilotUsed: (wasCopilotUsed: boolean) => set({ wasCopilotUsed }),
|
|
||||||
setShowWelcomeSidebar: (showWelcomeSidebar: boolean) => set({ showWelcomeSidebar }),
|
|
||||||
setShowCopilotSidebar: (showCopilotSidebar: boolean) => set({ showCopilotSidebar }),
|
|
||||||
setChatMessages: (chatMessages: CopilotMessage[]) => set({ chatMessages }),
|
|
||||||
setShouldIncludeInMessages: (shouldIncludeInMessages: boolean) => set({ shouldIncludeInMessages }),
|
|
||||||
setShowExplanationBubble: (showExplanationBubble: boolean) => set({ showExplanationBubble }),
|
|
||||||
setNotebookServerInfo: (notebookServerInfo: DataModels.NotebookWorkspaceConnectionInfo) =>
|
|
||||||
set({ notebookServerInfo }),
|
|
||||||
setContainerStatus: (containerStatus: ContainerInfo) => set({ containerStatus }),
|
|
||||||
setIsAllocatingContainer: (isAllocatingContainer: boolean) => set({ isAllocatingContainer }),
|
|
||||||
setSchemaAllocationInfo: (schemaAllocationInfo: CopilotSchemaAllocationInfo) => set({ schemaAllocationInfo }),
|
|
||||||
setCopilotEnabledforExecution: (copilotEnabledforExecution: boolean) => set({ copilotEnabledforExecution }),
|
|
||||||
|
|
||||||
resetContainerConnection: (): void => {
|
|
||||||
useTabs.getState().closeAllNotebookTabs(true);
|
|
||||||
useQueryCopilot.getState().setNotebookServerInfo(undefined);
|
|
||||||
useQueryCopilot.getState().setIsAllocatingContainer(false);
|
|
||||||
useQueryCopilot.getState().setContainerStatus({
|
|
||||||
status: undefined,
|
|
||||||
durationLeftInMinutes: undefined,
|
|
||||||
phoenixServerInfo: undefined,
|
|
||||||
});
|
|
||||||
useQueryCopilot.getState().setSchemaAllocationInfo({
|
|
||||||
databaseId: undefined,
|
|
||||||
containerId: undefined,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
resetQueryCopilotStates: () => {
|
|
||||||
set((state) => ({
|
|
||||||
...state,
|
|
||||||
generatedQuery: "",
|
generatedQuery: "",
|
||||||
likeQuery: false,
|
likeQuery: false,
|
||||||
userPrompt: "",
|
userPrompt: "",
|
||||||
@ -218,15 +111,15 @@ export const useQueryCopilot: QueryCopilotStore = create((set) => ({
|
|||||||
correlationId: "",
|
correlationId: "",
|
||||||
query: "SELECT * FROM c",
|
query: "SELECT * FROM c",
|
||||||
selectedQuery: "",
|
selectedQuery: "",
|
||||||
isGeneratingQuery: false,
|
isGeneratingQuery: null as boolean,
|
||||||
isGeneratingExplanation: false,
|
isGeneratingExplanation: false,
|
||||||
isExecuting: false,
|
isExecuting: false,
|
||||||
dislikeQuery: undefined,
|
dislikeQuery: undefined as (boolean | undefined),
|
||||||
showCallout: false,
|
showCallout: false,
|
||||||
showSamplePrompts: false,
|
showSamplePrompts: false,
|
||||||
queryIterator: undefined,
|
queryIterator: undefined as MinimalQueryIterator | undefined,
|
||||||
queryResults: undefined,
|
queryResults: undefined as QueryResults | undefined,
|
||||||
errors: [],
|
errors: [] as QueryError[],
|
||||||
isSamplePromptsOpen: false,
|
isSamplePromptsOpen: false,
|
||||||
showDeletePopup: false,
|
showDeletePopup: false,
|
||||||
showFeedbackBar: false,
|
showFeedbackBar: false,
|
||||||
@ -235,25 +128,135 @@ export const useQueryCopilot: QueryCopilotStore = create((set) => ({
|
|||||||
showInvalidQueryMessageBar: false,
|
showInvalidQueryMessageBar: false,
|
||||||
generatedQueryComments: "",
|
generatedQueryComments: "",
|
||||||
wasCopilotUsed: false,
|
wasCopilotUsed: false,
|
||||||
|
showWelcomeSidebar: true,
|
||||||
showCopilotSidebar: false,
|
showCopilotSidebar: false,
|
||||||
chatMessages: [],
|
chatMessages: [] as CopilotMessage[],
|
||||||
shouldIncludeInMessages: true,
|
shouldIncludeInMessages: true,
|
||||||
showExplanationBubble: false,
|
showExplanationBubble: false,
|
||||||
notebookServerInfo: {
|
notebookServerInfo: {
|
||||||
notebookServerEndpoint: undefined,
|
notebookServerEndpoint: undefined,
|
||||||
authToken: undefined,
|
authToken: undefined,
|
||||||
forwardingId: undefined,
|
forwardingId: undefined,
|
||||||
},
|
} as DataModels.NotebookWorkspaceConnectionInfo,
|
||||||
containerStatus: {
|
containerStatus: {
|
||||||
status: undefined,
|
status: undefined,
|
||||||
durationLeftInMinutes: undefined,
|
durationLeftInMinutes: undefined,
|
||||||
phoenixServerInfo: undefined,
|
phoenixServerInfo: undefined,
|
||||||
},
|
} as ContainerInfo,
|
||||||
schemaAllocationInfo: {
|
schemaAllocationInfo: {
|
||||||
databaseId: undefined,
|
databaseId: undefined,
|
||||||
containerId: undefined,
|
containerId: undefined,
|
||||||
},
|
} as CopilotSchemaAllocationInfo,
|
||||||
isAllocatingContainer: false,
|
isAllocatingContainer: false,
|
||||||
}));
|
copilotEnabledforExecution: false,
|
||||||
},
|
|
||||||
}));
|
setCopilotEnabled: (copilotEnabled: boolean) => set({ copilotEnabled }),
|
||||||
|
setCopilotUserDBEnabled: (copilotUserDBEnabled: boolean) => set({ copilotUserDBEnabled }),
|
||||||
|
setCopilotSampleDBEnabled: (copilotSampleDBEnabled: boolean) => set({ copilotSampleDBEnabled }),
|
||||||
|
openFeedbackModal: (generatedQuery: string, likeQuery: boolean, userPrompt: string) =>
|
||||||
|
set({ generatedQuery, likeQuery, userPrompt, showFeedbackModal: true }),
|
||||||
|
closeFeedbackModal: () => set({ showFeedbackModal: false }),
|
||||||
|
setHideFeedbackModalForLikedQueries: (hideFeedbackModalForLikedQueries: boolean) =>
|
||||||
|
set({ hideFeedbackModalForLikedQueries }),
|
||||||
|
refreshCorrelationId: () => set({ correlationId: guid() }),
|
||||||
|
setUserPrompt: (userPrompt: string) => set({ userPrompt }),
|
||||||
|
setQuery: (query: string) => set({ query }),
|
||||||
|
setGeneratedQuery: (generatedQuery: string) => set({ generatedQuery }),
|
||||||
|
setSelectedQuery: (selectedQuery: string) => set({ selectedQuery }),
|
||||||
|
setIsGeneratingQuery: (isGeneratingQuery: boolean) => set({ isGeneratingQuery }),
|
||||||
|
setIsGeneratingExplanation: (isGeneratingExplanation: boolean) => set({ isGeneratingExplanation }),
|
||||||
|
setIsExecuting: (isExecuting: boolean) => set({ isExecuting }),
|
||||||
|
setLikeQuery: (likeQuery: boolean) => set({ likeQuery }),
|
||||||
|
setDislikeQuery: (dislikeQuery: boolean | undefined) => set({ dislikeQuery }),
|
||||||
|
setShowCallout: (showCallout: boolean) => set({ showCallout }),
|
||||||
|
setShowSamplePrompts: (showSamplePrompts: boolean) => set({ showSamplePrompts }),
|
||||||
|
setQueryIterator: (queryIterator: MinimalQueryIterator | undefined) => set({ queryIterator }),
|
||||||
|
setQueryResults: (queryResults: QueryResults | undefined) => set({ queryResults }),
|
||||||
|
setErrors: (errors: QueryError[]) => set({ errors }),
|
||||||
|
setIsSamplePromptsOpen: (isSamplePromptsOpen: boolean) => set({ isSamplePromptsOpen }),
|
||||||
|
setShowDeletePopup: (showDeletePopup: boolean) => set({ showDeletePopup }),
|
||||||
|
setShowFeedbackBar: (showFeedbackBar: boolean) => set({ showFeedbackBar }),
|
||||||
|
setshowCopyPopup: (showCopyPopup: boolean) => set({ showCopyPopup }),
|
||||||
|
setShowErrorMessageBar: (showErrorMessageBar: boolean) => set({ showErrorMessageBar }),
|
||||||
|
setShowInvalidQueryMessageBar: (showInvalidQueryMessageBar: boolean) => set({ showInvalidQueryMessageBar }),
|
||||||
|
setGeneratedQueryComments: (generatedQueryComments: string) => set({ generatedQueryComments }),
|
||||||
|
setWasCopilotUsed: (wasCopilotUsed: boolean) => set({ wasCopilotUsed }),
|
||||||
|
setShowWelcomeSidebar: (showWelcomeSidebar: boolean) => set({ showWelcomeSidebar }),
|
||||||
|
setShowCopilotSidebar: (showCopilotSidebar: boolean) => set({ showCopilotSidebar }),
|
||||||
|
setChatMessages: (chatMessages: CopilotMessage[]) => set({ chatMessages }),
|
||||||
|
setShouldIncludeInMessages: (shouldIncludeInMessages: boolean) => set({ shouldIncludeInMessages }),
|
||||||
|
setShowExplanationBubble: (showExplanationBubble: boolean) => set({ showExplanationBubble }),
|
||||||
|
setNotebookServerInfo: (notebookServerInfo: DataModels.NotebookWorkspaceConnectionInfo) =>
|
||||||
|
set({ notebookServerInfo }),
|
||||||
|
setContainerStatus: (containerStatus: ContainerInfo) => set({ containerStatus }),
|
||||||
|
setIsAllocatingContainer: (isAllocatingContainer: boolean) => set({ isAllocatingContainer }),
|
||||||
|
setSchemaAllocationInfo: (schemaAllocationInfo: CopilotSchemaAllocationInfo) => set({ schemaAllocationInfo }),
|
||||||
|
setCopilotEnabledforExecution: (copilotEnabledforExecution: boolean) => set({ copilotEnabledforExecution }),
|
||||||
|
|
||||||
|
resetContainerConnection: (): void => {
|
||||||
|
useTabs.getState().closeAllNotebookTabs(true);
|
||||||
|
useQueryCopilot.getState().setNotebookServerInfo(undefined);
|
||||||
|
useQueryCopilot.getState().setIsAllocatingContainer(false);
|
||||||
|
useQueryCopilot.getState().setContainerStatus({
|
||||||
|
status: undefined,
|
||||||
|
durationLeftInMinutes: undefined,
|
||||||
|
phoenixServerInfo: undefined,
|
||||||
|
});
|
||||||
|
useQueryCopilot.getState().setSchemaAllocationInfo({
|
||||||
|
databaseId: undefined,
|
||||||
|
containerId: undefined,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
resetQueryCopilotStates: () => {
|
||||||
|
set((state) => ({
|
||||||
|
...state,
|
||||||
|
generatedQuery: "",
|
||||||
|
likeQuery: false,
|
||||||
|
userPrompt: "",
|
||||||
|
showFeedbackModal: false,
|
||||||
|
hideFeedbackModalForLikedQueries: false,
|
||||||
|
correlationId: "",
|
||||||
|
query: "SELECT * FROM c",
|
||||||
|
selectedQuery: "",
|
||||||
|
isGeneratingQuery: false,
|
||||||
|
isGeneratingExplanation: false,
|
||||||
|
isExecuting: false,
|
||||||
|
dislikeQuery: undefined,
|
||||||
|
showCallout: false,
|
||||||
|
showSamplePrompts: false,
|
||||||
|
queryIterator: undefined,
|
||||||
|
queryResults: undefined,
|
||||||
|
errors: [],
|
||||||
|
isSamplePromptsOpen: false,
|
||||||
|
showDeletePopup: false,
|
||||||
|
showFeedbackBar: false,
|
||||||
|
showCopyPopup: false,
|
||||||
|
showErrorMessageBar: false,
|
||||||
|
showInvalidQueryMessageBar: false,
|
||||||
|
generatedQueryComments: "",
|
||||||
|
wasCopilotUsed: false,
|
||||||
|
showCopilotSidebar: false,
|
||||||
|
chatMessages: [],
|
||||||
|
shouldIncludeInMessages: true,
|
||||||
|
showExplanationBubble: false,
|
||||||
|
notebookServerInfo: {
|
||||||
|
notebookServerEndpoint: undefined,
|
||||||
|
authToken: undefined,
|
||||||
|
forwardingId: undefined,
|
||||||
|
},
|
||||||
|
containerStatus: {
|
||||||
|
status: undefined,
|
||||||
|
durationLeftInMinutes: undefined,
|
||||||
|
phoenixServerInfo: undefined,
|
||||||
|
},
|
||||||
|
schemaAllocationInfo: {
|
||||||
|
databaseId: undefined,
|
||||||
|
containerId: undefined,
|
||||||
|
},
|
||||||
|
isAllocatingContainer: false,
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import create, { UseStore } from "zustand";
|
import { create } from "zustand";
|
||||||
|
|
||||||
export interface SidePanelState {
|
export interface SidePanelState {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@ -9,7 +9,7 @@ export interface SidePanelState {
|
|||||||
closeSidePanel: () => void;
|
closeSidePanel: () => void;
|
||||||
getRef?: React.RefObject<HTMLElement>; // Optional ref for focusing the last element.
|
getRef?: React.RefObject<HTMLElement>; // Optional ref for focusing the last element.
|
||||||
}
|
}
|
||||||
export const useSidePanel: UseStore<SidePanelState> = create((set) => ({
|
export const useSidePanel = create<SidePanelState>((set) => ({
|
||||||
isOpen: false,
|
isOpen: false,
|
||||||
panelWidth: "440px",
|
panelWidth: "440px",
|
||||||
openSidePanel: (headerText, panelContent, panelWidth = "440px") =>
|
openSidePanel: (headerText, panelContent, panelWidth = "440px") =>
|
||||||
|
@ -7,7 +7,8 @@ import {
|
|||||||
OPEN_TABS_SUBCOMPONENT_NAME,
|
OPEN_TABS_SUBCOMPONENT_NAME,
|
||||||
saveSubComponentState,
|
saveSubComponentState,
|
||||||
} from "Shared/AppStatePersistenceUtility";
|
} from "Shared/AppStatePersistenceUtility";
|
||||||
import create, { UseStore } from "zustand";
|
import { create } from "zustand";
|
||||||
|
import { subscribeWithSelector } from "zustand/middleware";
|
||||||
import * as ViewModels from "../Contracts/ViewModels";
|
import * as ViewModels from "../Contracts/ViewModels";
|
||||||
import { CollectionTabKind } from "../Contracts/ViewModels";
|
import { CollectionTabKind } from "../Contracts/ViewModels";
|
||||||
import NotebookTabV2 from "../Explorer/Tabs/NotebookV2Tab";
|
import NotebookTabV2 from "../Explorer/Tabs/NotebookV2Tab";
|
||||||
@ -51,194 +52,198 @@ export enum ReactTabKind {
|
|||||||
QueryCopilot,
|
QueryCopilot,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useTabs: UseStore<TabsState> = create((set, get) => ({
|
export const useTabs = create<TabsState>()(
|
||||||
openedTabs: [] as TabsBase[],
|
subscribeWithSelector(
|
||||||
openedReactTabs: [ReactTabKind.Home],
|
(set, get) => ({
|
||||||
activeTab: undefined as TabsBase,
|
openedTabs: [] as TabsBase[],
|
||||||
activeReactTab: ReactTabKind.Home,
|
openedReactTabs: [ReactTabKind.Home],
|
||||||
queryCopilotTabInitialInput: "",
|
activeTab: undefined as TabsBase,
|
||||||
isTabExecuting: false,
|
activeReactTab: ReactTabKind.Home,
|
||||||
isQueryErrorThrown: false,
|
queryCopilotTabInitialInput: "",
|
||||||
activateTab: (tab: TabsBase): void => {
|
isTabExecuting: false,
|
||||||
if (get().openedTabs.some((openedTab) => openedTab.tabId === tab.tabId)) {
|
isQueryErrorThrown: false,
|
||||||
set({ activeTab: tab, activeReactTab: undefined });
|
activateTab: (tab: TabsBase): void => {
|
||||||
tab.onActivate();
|
if (get().openedTabs.some((openedTab) => openedTab.tabId === tab.tabId)) {
|
||||||
}
|
set({ activeTab: tab, activeReactTab: undefined });
|
||||||
},
|
tab.onActivate();
|
||||||
activateNewTab: (tab: TabsBase): void => {
|
|
||||||
set((state) => ({ openedTabs: [...state.openedTabs, tab], activeTab: tab, activeReactTab: undefined }));
|
|
||||||
tab.triggerPersistState = get().persistTabsState;
|
|
||||||
tab.onActivate();
|
|
||||||
get().persistTabsState();
|
|
||||||
},
|
|
||||||
activateReactTab: (tabKind: ReactTabKind): void => {
|
|
||||||
// Clear the selected node when switching to a react tab.
|
|
||||||
useSelectedNode.getState().setSelectedNode(undefined);
|
|
||||||
set({ activeTab: undefined, activeReactTab: tabKind });
|
|
||||||
},
|
|
||||||
updateTab: (tab: TabsBase) => {
|
|
||||||
if (get().activeTab?.tabId === tab.tabId) {
|
|
||||||
set({ activeTab: tab });
|
|
||||||
}
|
|
||||||
|
|
||||||
set((state) => ({
|
|
||||||
openedTabs: state.openedTabs.map((openedTab) => {
|
|
||||||
if (openedTab.tabId === tab.tabId) {
|
|
||||||
return tab;
|
|
||||||
}
|
}
|
||||||
return openedTab;
|
},
|
||||||
}),
|
activateNewTab: (tab: TabsBase): void => {
|
||||||
}));
|
set((state) => ({ openedTabs: [...state.openedTabs, tab], activeTab: tab, activeReactTab: undefined }));
|
||||||
},
|
tab.triggerPersistState = get().persistTabsState;
|
||||||
getTabs: (tabKind: ViewModels.CollectionTabKind, comparator?: (tab: TabsBase) => boolean): TabsBase[] =>
|
tab.onActivate();
|
||||||
get().openedTabs.filter((tab) => tab.tabKind === tabKind && (!comparator || comparator(tab))),
|
get().persistTabsState();
|
||||||
refreshActiveTab: (comparator: (tab: TabsBase) => boolean): void => {
|
},
|
||||||
// ensures that the tab selects/highlights the right node based on resource tree expand/collapse state
|
activateReactTab: (tabKind: ReactTabKind): void => {
|
||||||
const activeTab = get().activeTab;
|
// Clear the selected node when switching to a react tab.
|
||||||
activeTab && comparator(activeTab) && activeTab.onActivate();
|
useSelectedNode.getState().setSelectedNode(undefined);
|
||||||
},
|
set({ activeTab: undefined, activeReactTab: tabKind });
|
||||||
closeTabsByComparator: (comparator: (tab: TabsBase) => boolean): void =>
|
},
|
||||||
get()
|
updateTab: (tab: TabsBase) => {
|
||||||
.openedTabs.filter(comparator)
|
if (get().activeTab?.tabId === tab.tabId) {
|
||||||
.forEach((tab) => tab.onCloseTabButtonClick()),
|
set({ activeTab: tab });
|
||||||
closeTab: (tab: TabsBase): void => {
|
|
||||||
let tabIndex: number;
|
|
||||||
const { activeTab, openedTabs, openedReactTabs } = get();
|
|
||||||
const updatedTabs = openedTabs.filter((openedTab, index) => {
|
|
||||||
if (tab.tabId === openedTab.tabId) {
|
|
||||||
tabIndex = index;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
if (updatedTabs.length === 0 && !isFabricMirrored()) {
|
|
||||||
set({ activeTab: undefined, activeReactTab: undefined });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tab.tabId === activeTab?.tabId && tabIndex !== -1) {
|
|
||||||
const tabToTheRight = updatedTabs[tabIndex];
|
|
||||||
const lastOpenTab = updatedTabs[updatedTabs.length - 1];
|
|
||||||
const newActiveTab = tabToTheRight ?? lastOpenTab;
|
|
||||||
set({ activeTab: newActiveTab });
|
|
||||||
if (newActiveTab) {
|
|
||||||
newActiveTab.onActivate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
set({ openedTabs: updatedTabs });
|
|
||||||
|
|
||||||
if (updatedTabs.length === 0 && openedReactTabs.length > 0) {
|
|
||||||
set({ activeTab: undefined, activeReactTab: openedReactTabs[openedReactTabs.length - 1] });
|
|
||||||
}
|
|
||||||
|
|
||||||
get().persistTabsState();
|
|
||||||
},
|
|
||||||
closeAllNotebookTabs: (hardClose): void => {
|
|
||||||
const isNotebook = (tabKind: CollectionTabKind): boolean => {
|
|
||||||
if (
|
|
||||||
tabKind === CollectionTabKind.Notebook ||
|
|
||||||
tabKind === CollectionTabKind.NotebookV2 ||
|
|
||||||
tabKind === CollectionTabKind.SchemaAnalyzer ||
|
|
||||||
tabKind === CollectionTabKind.Terminal
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
const tabList = get().openedTabs;
|
|
||||||
if (tabList && tabList.length > 0) {
|
|
||||||
tabList.forEach((tab: NotebookTabV2) => {
|
|
||||||
const tabKind: CollectionTabKind = tab.tabKind;
|
|
||||||
if (tabKind && isNotebook(tabKind)) {
|
|
||||||
tab.onCloseTabButtonClick(hardClose);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
if (get().openedTabs.length === 0 && !isFabricMirrored()) {
|
set((state) => ({
|
||||||
set({ activeTab: undefined, activeReactTab: undefined });
|
openedTabs: state.openedTabs.map((openedTab) => {
|
||||||
}
|
if (openedTab.tabId === tab.tabId) {
|
||||||
}
|
return tab;
|
||||||
},
|
}
|
||||||
openAndActivateReactTab: (tabKind: ReactTabKind) => {
|
return openedTab;
|
||||||
if (get().openedReactTabs.indexOf(tabKind) === -1) {
|
}),
|
||||||
set((state) => ({
|
}));
|
||||||
openedReactTabs: [...state.openedReactTabs, tabKind],
|
},
|
||||||
}));
|
getTabs: (tabKind: ViewModels.CollectionTabKind, comparator?: (tab: TabsBase) => boolean): TabsBase[] =>
|
||||||
}
|
get().openedTabs.filter((tab) => tab.tabKind === tabKind && (!comparator || comparator(tab))),
|
||||||
|
refreshActiveTab: (comparator: (tab: TabsBase) => boolean): void => {
|
||||||
|
// ensures that the tab selects/highlights the right node based on resource tree expand/collapse state
|
||||||
|
const activeTab = get().activeTab;
|
||||||
|
activeTab && comparator(activeTab) && activeTab.onActivate();
|
||||||
|
},
|
||||||
|
closeTabsByComparator: (comparator: (tab: TabsBase) => boolean): void =>
|
||||||
|
get()
|
||||||
|
.openedTabs.filter(comparator)
|
||||||
|
.forEach((tab) => tab.onCloseTabButtonClick()),
|
||||||
|
closeTab: (tab: TabsBase): void => {
|
||||||
|
let tabIndex: number;
|
||||||
|
const { activeTab, openedTabs, openedReactTabs } = get();
|
||||||
|
const updatedTabs = openedTabs.filter((openedTab, index) => {
|
||||||
|
if (tab.tabId === openedTab.tabId) {
|
||||||
|
tabIndex = index;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
if (updatedTabs.length === 0 && !isFabricMirrored()) {
|
||||||
|
set({ activeTab: undefined, activeReactTab: undefined });
|
||||||
|
}
|
||||||
|
|
||||||
set({ activeTab: undefined, activeReactTab: tabKind });
|
if (tab.tabId === activeTab?.tabId && tabIndex !== -1) {
|
||||||
},
|
const tabToTheRight = updatedTabs[tabIndex];
|
||||||
closeReactTab: (tabKind: ReactTabKind) => {
|
const lastOpenTab = updatedTabs[updatedTabs.length - 1];
|
||||||
const { activeReactTab, openedTabs, openedReactTabs } = get();
|
const newActiveTab = tabToTheRight ?? lastOpenTab;
|
||||||
const updatedOpenedReactTabs = openedReactTabs.filter((tab: ReactTabKind) => tabKind !== tab);
|
set({ activeTab: newActiveTab });
|
||||||
if (activeReactTab === tabKind) {
|
if (newActiveTab) {
|
||||||
openedTabs?.length > 0
|
newActiveTab.onActivate();
|
||||||
? set({ activeTab: openedTabs[0], activeReactTab: undefined })
|
}
|
||||||
: set({ activeTab: undefined, activeReactTab: updatedOpenedReactTabs[0] });
|
}
|
||||||
}
|
|
||||||
|
|
||||||
set({ openedReactTabs: updatedOpenedReactTabs });
|
set({ openedTabs: updatedTabs });
|
||||||
},
|
|
||||||
setQueryCopilotTabInitialInput: (input: string) => set({ queryCopilotTabInitialInput: input }),
|
|
||||||
setIsTabExecuting: (state: boolean) => {
|
|
||||||
set({ isTabExecuting: state });
|
|
||||||
},
|
|
||||||
setIsQueryErrorThrown: (state: boolean) => {
|
|
||||||
set({ isQueryErrorThrown: state });
|
|
||||||
},
|
|
||||||
getCurrentTabIndex: () => {
|
|
||||||
const state = get();
|
|
||||||
if (state.activeReactTab !== undefined) {
|
|
||||||
return state.openedReactTabs.indexOf(state.activeReactTab);
|
|
||||||
} else if (state.activeTab !== undefined) {
|
|
||||||
const nonReactTabIndex = state.openedTabs.indexOf(state.activeTab);
|
|
||||||
if (nonReactTabIndex !== -1) {
|
|
||||||
return state.openedReactTabs.length + nonReactTabIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
if (updatedTabs.length === 0 && openedReactTabs.length > 0) {
|
||||||
},
|
set({ activeTab: undefined, activeReactTab: openedReactTabs[openedReactTabs.length - 1] });
|
||||||
selectTabByIndex: (index: number) => {
|
}
|
||||||
const state = get();
|
|
||||||
const totalTabCount = state.openedReactTabs.length + state.openedTabs.length;
|
|
||||||
const clampedIndex = clamp(index, totalTabCount - 1, 0);
|
|
||||||
|
|
||||||
if (clampedIndex < state.openedReactTabs.length) {
|
get().persistTabsState();
|
||||||
set({ activeTab: undefined, activeReactTab: state.openedReactTabs[clampedIndex] });
|
},
|
||||||
} else {
|
closeAllNotebookTabs: (hardClose): void => {
|
||||||
set({ activeTab: state.openedTabs[clampedIndex - state.openedReactTabs.length], activeReactTab: undefined });
|
const isNotebook = (tabKind: CollectionTabKind): boolean => {
|
||||||
}
|
if (
|
||||||
},
|
tabKind === CollectionTabKind.Notebook ||
|
||||||
selectLeftTab: () => {
|
tabKind === CollectionTabKind.NotebookV2 ||
|
||||||
const state = get();
|
tabKind === CollectionTabKind.SchemaAnalyzer ||
|
||||||
state.selectTabByIndex(state.getCurrentTabIndex() - 1);
|
tabKind === CollectionTabKind.Terminal
|
||||||
},
|
) {
|
||||||
selectRightTab: () => {
|
return true;
|
||||||
const state = get();
|
}
|
||||||
state.selectTabByIndex(state.getCurrentTabIndex() + 1);
|
return false;
|
||||||
},
|
};
|
||||||
closeActiveTab: () => {
|
|
||||||
const state = get();
|
|
||||||
if (state.activeReactTab !== undefined) {
|
|
||||||
state.closeReactTab(state.activeReactTab);
|
|
||||||
} else if (state.activeTab !== undefined) {
|
|
||||||
state.closeTab(state.activeTab);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
closeAllTabs: () => {
|
|
||||||
set({ openedTabs: [], openedReactTabs: [], activeTab: undefined, activeReactTab: undefined });
|
|
||||||
},
|
|
||||||
persistTabsState: () => {
|
|
||||||
const state = get();
|
|
||||||
const openTabsStates = state.openedTabs.map((tab) => tab.getPersistedState());
|
|
||||||
|
|
||||||
saveSubComponentState<OpenTab[]>(
|
const tabList = get().openedTabs;
|
||||||
AppStateComponentNames.DataExplorerAction,
|
if (tabList && tabList.length > 0) {
|
||||||
OPEN_TABS_SUBCOMPONENT_NAME,
|
tabList.forEach((tab: NotebookTabV2) => {
|
||||||
undefined,
|
const tabKind: CollectionTabKind = tab.tabKind;
|
||||||
openTabsStates,
|
if (tabKind && isNotebook(tabKind)) {
|
||||||
);
|
tab.onCloseTabButtonClick(hardClose);
|
||||||
},
|
}
|
||||||
}));
|
});
|
||||||
|
|
||||||
|
if (get().openedTabs.length === 0 && !isFabricMirrored()) {
|
||||||
|
set({ activeTab: undefined, activeReactTab: undefined });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
openAndActivateReactTab: (tabKind: ReactTabKind) => {
|
||||||
|
if (get().openedReactTabs.indexOf(tabKind) === -1) {
|
||||||
|
set((state) => ({
|
||||||
|
openedReactTabs: [...state.openedReactTabs, tabKind],
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
set({ activeTab: undefined, activeReactTab: tabKind });
|
||||||
|
},
|
||||||
|
closeReactTab: (tabKind: ReactTabKind) => {
|
||||||
|
const { activeReactTab, openedTabs, openedReactTabs } = get();
|
||||||
|
const updatedOpenedReactTabs = openedReactTabs.filter((tab: ReactTabKind) => tabKind !== tab);
|
||||||
|
if (activeReactTab === tabKind) {
|
||||||
|
openedTabs?.length > 0
|
||||||
|
? set({ activeTab: openedTabs[0], activeReactTab: undefined })
|
||||||
|
: set({ activeTab: undefined, activeReactTab: updatedOpenedReactTabs[0] });
|
||||||
|
}
|
||||||
|
|
||||||
|
set({ openedReactTabs: updatedOpenedReactTabs });
|
||||||
|
},
|
||||||
|
setQueryCopilotTabInitialInput: (input: string) => set({ queryCopilotTabInitialInput: input }),
|
||||||
|
setIsTabExecuting: (state: boolean) => {
|
||||||
|
set({ isTabExecuting: state });
|
||||||
|
},
|
||||||
|
setIsQueryErrorThrown: (state: boolean) => {
|
||||||
|
set({ isQueryErrorThrown: state });
|
||||||
|
},
|
||||||
|
getCurrentTabIndex: () => {
|
||||||
|
const state = get();
|
||||||
|
if (state.activeReactTab !== undefined) {
|
||||||
|
return state.openedReactTabs.indexOf(state.activeReactTab);
|
||||||
|
} else if (state.activeTab !== undefined) {
|
||||||
|
const nonReactTabIndex = state.openedTabs.indexOf(state.activeTab);
|
||||||
|
if (nonReactTabIndex !== -1) {
|
||||||
|
return state.openedReactTabs.length + nonReactTabIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
},
|
||||||
|
selectTabByIndex: (index: number) => {
|
||||||
|
const state = get();
|
||||||
|
const totalTabCount = state.openedReactTabs.length + state.openedTabs.length;
|
||||||
|
const clampedIndex = clamp(index, totalTabCount - 1, 0);
|
||||||
|
|
||||||
|
if (clampedIndex < state.openedReactTabs.length) {
|
||||||
|
set({ activeTab: undefined, activeReactTab: state.openedReactTabs[clampedIndex] });
|
||||||
|
} else {
|
||||||
|
set({ activeTab: state.openedTabs[clampedIndex - state.openedReactTabs.length], activeReactTab: undefined });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selectLeftTab: () => {
|
||||||
|
const state = get();
|
||||||
|
state.selectTabByIndex(state.getCurrentTabIndex() - 1);
|
||||||
|
},
|
||||||
|
selectRightTab: () => {
|
||||||
|
const state = get();
|
||||||
|
state.selectTabByIndex(state.getCurrentTabIndex() + 1);
|
||||||
|
},
|
||||||
|
closeActiveTab: () => {
|
||||||
|
const state = get();
|
||||||
|
if (state.activeReactTab !== undefined) {
|
||||||
|
state.closeReactTab(state.activeReactTab);
|
||||||
|
} else if (state.activeTab !== undefined) {
|
||||||
|
state.closeTab(state.activeTab);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
closeAllTabs: () => {
|
||||||
|
set({ openedTabs: [], openedReactTabs: [], activeTab: undefined, activeReactTab: undefined });
|
||||||
|
},
|
||||||
|
persistTabsState: () => {
|
||||||
|
const state = get();
|
||||||
|
const openTabsStates = state.openedTabs.map((tab) => tab.getPersistedState());
|
||||||
|
|
||||||
|
saveSubComponentState<OpenTab[]>(
|
||||||
|
AppStateComponentNames.DataExplorerAction,
|
||||||
|
OPEN_TABS_SUBCOMPONENT_NAME,
|
||||||
|
undefined,
|
||||||
|
openTabsStates,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Collection } from "Contracts/ViewModels";
|
import { Collection } from "Contracts/ViewModels";
|
||||||
import create, { UseStore } from "zustand";
|
import { create } from "zustand";
|
||||||
|
|
||||||
interface TeachingBubbleState {
|
interface TeachingBubbleState {
|
||||||
step: number;
|
step: number;
|
||||||
@ -12,7 +12,7 @@ interface TeachingBubbleState {
|
|||||||
setSampleCollection: (sampleCollection: Collection) => void;
|
setSampleCollection: (sampleCollection: Collection) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useTeachingBubble: UseStore<TeachingBubbleState> = create((set) => ({
|
export const useTeachingBubble = create<TeachingBubbleState>((set) => ({
|
||||||
step: 1,
|
step: 1,
|
||||||
isSampleDBExpanded: false,
|
isSampleDBExpanded: false,
|
||||||
isDocumentsTabOpened: false,
|
isDocumentsTabOpened: false,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import postRobot from "post-robot";
|
import postRobot from "post-robot";
|
||||||
import create, { UseStore } from "zustand";
|
import { create } from "zustand";
|
||||||
|
|
||||||
interface TerminalState {
|
interface TerminalState {
|
||||||
terminalWindow: Window;
|
terminalWindow: Window;
|
||||||
@ -7,7 +7,7 @@ interface TerminalState {
|
|||||||
sendMessage: (message: string) => void;
|
sendMessage: (message: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useTerminal: UseStore<TerminalState> = create((set, get) => ({
|
export const useTerminal = create<TerminalState>((set, get) => ({
|
||||||
terminalWindow: undefined,
|
terminalWindow: undefined,
|
||||||
setTerminal: (terminalWindow: Window) => {
|
setTerminal: (terminalWindow: Window) => {
|
||||||
set({ terminalWindow });
|
set({ terminalWindow });
|
||||||
|
Loading…
x
Reference in New Issue
Block a user