mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
chore: upgrade tanstack/react-query to 5.77.0 (#18039)
This commit is contained in:
@@ -28,7 +28,7 @@ import { DecoratorHelpers } from "@storybook/addon-themes";
|
|||||||
import isChromatic from "chromatic/isChromatic";
|
import isChromatic from "chromatic/isChromatic";
|
||||||
import { StrictMode } from "react";
|
import { StrictMode } from "react";
|
||||||
import { HelmetProvider } from "react-helmet-async";
|
import { HelmetProvider } from "react-helmet-async";
|
||||||
import { QueryClient, QueryClientProvider, parseQueryArgs } from "react-query";
|
import { QueryClient, QueryClientProvider } from "react-query";
|
||||||
import { withRouter } from "storybook-addon-remix-react-router";
|
import { withRouter } from "storybook-addon-remix-react-router";
|
||||||
import "theme/globalFonts";
|
import "theme/globalFonts";
|
||||||
import themes from "../src/theme";
|
import themes from "../src/theme";
|
||||||
@@ -114,20 +114,7 @@ function withQuery(Story, { parameters }) {
|
|||||||
|
|
||||||
if (parameters.queries) {
|
if (parameters.queries) {
|
||||||
for (const query of parameters.queries) {
|
for (const query of parameters.queries) {
|
||||||
if (query.isError) {
|
queryClient.setQueryData(query.key, query.data);
|
||||||
// Based on `setQueryData`, but modified to set the result as an error.
|
|
||||||
const cache = queryClient.getQueryCache();
|
|
||||||
const parsedOptions = parseQueryArgs(query.key);
|
|
||||||
const defaultedOptions = queryClient.defaultQueryOptions(parsedOptions);
|
|
||||||
// Adds an uninitialized response to the cache, which we can now mutate.
|
|
||||||
const cachedQuery = cache.build(queryClient, defaultedOptions);
|
|
||||||
// Setting `manual` prevents retries.
|
|
||||||
cachedQuery.setData(undefined, { manual: true });
|
|
||||||
// Set the `error` value and the appropriate status.
|
|
||||||
cachedQuery.setState({ error: query.data, status: "error" });
|
|
||||||
} else {
|
|
||||||
queryClient.setQueryData(query.key, query.data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -69,7 +69,7 @@
|
|||||||
"@radix-ui/react-slot": "1.1.1",
|
"@radix-ui/react-slot": "1.1.1",
|
||||||
"@radix-ui/react-switch": "1.1.1",
|
"@radix-ui/react-switch": "1.1.1",
|
||||||
"@radix-ui/react-tooltip": "1.1.7",
|
"@radix-ui/react-tooltip": "1.1.7",
|
||||||
"@tanstack/react-query-devtools": "4.35.3",
|
"@tanstack/react-query-devtools": "5.77.0",
|
||||||
"@xterm/addon-canvas": "0.7.0",
|
"@xterm/addon-canvas": "0.7.0",
|
||||||
"@xterm/addon-fit": "0.10.0",
|
"@xterm/addon-fit": "0.10.0",
|
||||||
"@xterm/addon-unicode11": "0.8.0",
|
"@xterm/addon-unicode11": "0.8.0",
|
||||||
@@ -103,7 +103,7 @@
|
|||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
"react-helmet-async": "2.0.5",
|
"react-helmet-async": "2.0.5",
|
||||||
"react-markdown": "9.0.3",
|
"react-markdown": "9.0.3",
|
||||||
"react-query": "npm:@tanstack/react-query@4.35.3",
|
"react-query": "npm:@tanstack/react-query@5.77.0",
|
||||||
"react-router-dom": "6.26.2",
|
"react-router-dom": "6.26.2",
|
||||||
"react-syntax-highlighter": "15.6.1",
|
"react-syntax-highlighter": "15.6.1",
|
||||||
"react-virtualized-auto-sizer": "1.0.24",
|
"react-virtualized-auto-sizer": "1.0.24",
|
||||||
|
|||||||
Generated
+23
-75
@@ -119,8 +119,8 @@ importers:
|
|||||||
specifier: 1.1.7
|
specifier: 1.1.7
|
||||||
version: 1.1.7(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 1.1.7(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
'@tanstack/react-query-devtools':
|
'@tanstack/react-query-devtools':
|
||||||
specifier: 4.35.3
|
specifier: 5.77.0
|
||||||
version: 4.35.3(@tanstack/react-query@4.35.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 5.77.0(@tanstack/react-query@5.77.0(react@18.3.1))(react@18.3.1)
|
||||||
'@xterm/addon-canvas':
|
'@xterm/addon-canvas':
|
||||||
specifier: 0.7.0
|
specifier: 0.7.0
|
||||||
version: 0.7.0(@xterm/xterm@5.5.0)
|
version: 0.7.0(@xterm/xterm@5.5.0)
|
||||||
@@ -221,8 +221,8 @@ importers:
|
|||||||
specifier: 9.0.3
|
specifier: 9.0.3
|
||||||
version: 9.0.3(@types/react@18.3.12)(react@18.3.1)
|
version: 9.0.3(@types/react@18.3.12)(react@18.3.1)
|
||||||
react-query:
|
react-query:
|
||||||
specifier: npm:@tanstack/react-query@4.35.3
|
specifier: npm:@tanstack/react-query@5.77.0
|
||||||
version: '@tanstack/react-query@4.35.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)'
|
version: '@tanstack/react-query@5.77.0(react@18.3.1)'
|
||||||
react-router-dom:
|
react-router-dom:
|
||||||
specifier: 6.26.2
|
specifier: 6.26.2
|
||||||
version: 6.26.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 6.26.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
@@ -2398,31 +2398,22 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1'
|
tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1'
|
||||||
|
|
||||||
'@tanstack/match-sorter-utils@8.8.4':
|
'@tanstack/query-core@5.77.0':
|
||||||
resolution: {integrity: sha512-rKH8LjZiszWEvmi01NR72QWZ8m4xmXre0OOwlRGnjU01Eqz/QnN+cqpty2PJ0efHblq09+KilvyR7lsbzmXVEw==, tarball: https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.8.4.tgz}
|
resolution: {integrity: sha512-PFeWjgMQjOsnxBwnW/TJoO0pCja2dzuMQoZ3Diho7dPz7FnTUwTrjNmdf08evrhSE5nvPIKeqV6R0fvQfmhGeg==, tarball: https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.77.0.tgz}
|
||||||
engines: {node: '>=12'}
|
|
||||||
|
|
||||||
'@tanstack/query-core@4.35.3':
|
'@tanstack/query-devtools@5.76.0':
|
||||||
resolution: {integrity: sha512-PS+WEjd9wzKTyNjjQymvcOe1yg8f3wYc6mD+vb6CKyZAKvu4sIJwryfqfBULITKCla7P9C4l5e9RXePHvZOZeQ==, tarball: https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.35.3.tgz}
|
resolution: {integrity: sha512-1p92nqOBPYVqVDU0Ua5nzHenC6EGZNrLnB2OZphYw8CNA1exuvI97FVgIKON7Uug3uQqvH/QY8suUKpQo8qHNQ==, tarball: https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.76.0.tgz}
|
||||||
|
|
||||||
'@tanstack/react-query-devtools@4.35.3':
|
'@tanstack/react-query-devtools@5.77.0':
|
||||||
resolution: {integrity: sha512-UvLT7qPzCuCZ3NfjwsOqDUVN84JvSOuW6ukrjZmSqgjPqVxD6ra/HUp1CEOatQY2TRvKCp8y1lTVu+trXM30fg==, tarball: https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-4.35.3.tgz}
|
resolution: {integrity: sha512-Dwvs+ksXiK1tW4YnTtHwYPO5+d8IUk1l8QQJ4aGEIqKz6uTLu/67NIo7EnUF0G/Edv+UOn9P1V3tYWuVfvhbmg==, tarball: https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.77.0.tgz}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@tanstack/react-query': ^4.35.3
|
'@tanstack/react-query': ^5.77.0
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
react: ^18 || ^19
|
||||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
|
|
||||||
|
|
||||||
'@tanstack/react-query@4.35.3':
|
'@tanstack/react-query@5.77.0':
|
||||||
resolution: {integrity: sha512-UgTPioip/rGG3EQilXfA2j4BJkhEQsR+KAbF+KIuvQ7j4MkgnTCJF01SfRpIRNtQTlEfz/+IL7+jP8WA8bFbsw==, tarball: https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.35.3.tgz}
|
resolution: {integrity: sha512-jX52ot8WxWzWnAknpRSEWj6PTR/7nkULOfoiaVPk6nKu0otwt30UMBC9PTg/m1x0uhz1g71/imwjViTm/oYHxA==, tarball: https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.77.0.tgz}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
react: ^18 || ^19
|
||||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
|
|
||||||
react-native: '*'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
react-dom:
|
|
||||||
optional: true
|
|
||||||
react-native:
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@testing-library/dom@10.4.0':
|
'@testing-library/dom@10.4.0':
|
||||||
resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==, tarball: https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz}
|
resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==, tarball: https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz}
|
||||||
@@ -3258,10 +3249,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==, tarball: https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz}
|
resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==, tarball: https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
copy-anything@3.0.5:
|
|
||||||
resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==, tarball: https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz}
|
|
||||||
engines: {node: '>=12.13'}
|
|
||||||
|
|
||||||
core-util-is@1.0.3:
|
core-util-is@1.0.3:
|
||||||
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==, tarball: https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz}
|
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==, tarball: https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz}
|
||||||
|
|
||||||
@@ -3635,6 +3622,7 @@ packages:
|
|||||||
eslint@8.52.0:
|
eslint@8.52.0:
|
||||||
resolution: {integrity: sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==, tarball: https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz}
|
resolution: {integrity: sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==, tarball: https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
|
deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options.
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
espree@9.6.1:
|
espree@9.6.1:
|
||||||
@@ -4219,10 +4207,6 @@ packages:
|
|||||||
is-weakset@2.0.2:
|
is-weakset@2.0.2:
|
||||||
resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==, tarball: https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz}
|
resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==, tarball: https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz}
|
||||||
|
|
||||||
is-what@4.1.16:
|
|
||||||
resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==, tarball: https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz}
|
|
||||||
engines: {node: '>=12.13'}
|
|
||||||
|
|
||||||
is-wsl@2.2.0:
|
is-wsl@2.2.0:
|
||||||
resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==, tarball: https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz}
|
resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==, tarball: https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -5516,9 +5500,6 @@ packages:
|
|||||||
remark-stringify@11.0.0:
|
remark-stringify@11.0.0:
|
||||||
resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==, tarball: https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz}
|
resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==, tarball: https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz}
|
||||||
|
|
||||||
remove-accents@0.4.2:
|
|
||||||
resolution: {integrity: sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==, tarball: https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz}
|
|
||||||
|
|
||||||
require-directory@2.1.1:
|
require-directory@2.1.1:
|
||||||
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==, tarball: https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz}
|
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==, tarball: https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -5835,10 +5816,6 @@ packages:
|
|||||||
engines: {node: '>=16 || 14 >=14.17'}
|
engines: {node: '>=16 || 14 >=14.17'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
superjson@1.13.3:
|
|
||||||
resolution: {integrity: sha512-mJiVjfd2vokfDxsQPOwJ/PtanO87LhpYY88ubI5dUB1Ab58Txbyje3+jpm+/83R/fevaq/107NNhtYBLuoTrFg==, tarball: https://registry.npmjs.org/superjson/-/superjson-1.13.3.tgz}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
|
|
||||||
supports-color@5.5.0:
|
supports-color@5.5.0:
|
||||||
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==, tarball: https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz}
|
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==, tarball: https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@@ -6152,11 +6129,6 @@ packages:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
use-sync-external-store@1.2.0:
|
|
||||||
resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==, tarball: https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz}
|
|
||||||
peerDependencies:
|
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
|
||||||
|
|
||||||
use-sync-external-store@1.4.0:
|
use-sync-external-store@1.4.0:
|
||||||
resolution: {integrity: sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==, tarball: https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz}
|
resolution: {integrity: sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==, tarball: https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -8523,28 +8495,20 @@ snapshots:
|
|||||||
postcss-selector-parser: 6.0.10
|
postcss-selector-parser: 6.0.10
|
||||||
tailwindcss: 3.4.17(ts-node@10.9.2(@swc/core@1.3.38)(@types/node@20.17.16)(typescript@5.6.3))
|
tailwindcss: 3.4.17(ts-node@10.9.2(@swc/core@1.3.38)(@types/node@20.17.16)(typescript@5.6.3))
|
||||||
|
|
||||||
'@tanstack/match-sorter-utils@8.8.4':
|
'@tanstack/query-core@5.77.0': {}
|
||||||
dependencies:
|
|
||||||
remove-accents: 0.4.2
|
|
||||||
|
|
||||||
'@tanstack/query-core@4.35.3': {}
|
'@tanstack/query-devtools@5.76.0': {}
|
||||||
|
|
||||||
'@tanstack/react-query-devtools@4.35.3(@tanstack/react-query@4.35.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
'@tanstack/react-query-devtools@5.77.0(@tanstack/react-query@5.77.0(react@18.3.1))(react@18.3.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tanstack/match-sorter-utils': 8.8.4
|
'@tanstack/query-devtools': 5.76.0
|
||||||
'@tanstack/react-query': 4.35.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@tanstack/react-query': 5.77.0(react@18.3.1)
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
|
||||||
superjson: 1.13.3
|
|
||||||
use-sync-external-store: 1.2.0(react@18.3.1)
|
|
||||||
|
|
||||||
'@tanstack/react-query@4.35.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
'@tanstack/react-query@5.77.0(react@18.3.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tanstack/query-core': 4.35.3
|
'@tanstack/query-core': 5.77.0
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
use-sync-external-store: 1.2.0(react@18.3.1)
|
|
||||||
optionalDependencies:
|
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
|
||||||
|
|
||||||
'@testing-library/dom@10.4.0':
|
'@testing-library/dom@10.4.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -9447,10 +9411,6 @@ snapshots:
|
|||||||
|
|
||||||
cookie@0.7.2: {}
|
cookie@0.7.2: {}
|
||||||
|
|
||||||
copy-anything@3.0.5:
|
|
||||||
dependencies:
|
|
||||||
is-what: 4.1.16
|
|
||||||
|
|
||||||
core-util-is@1.0.3: {}
|
core-util-is@1.0.3: {}
|
||||||
|
|
||||||
cosmiconfig@7.1.0:
|
cosmiconfig@7.1.0:
|
||||||
@@ -10542,8 +10502,6 @@ snapshots:
|
|||||||
call-bind: 1.0.8
|
call-bind: 1.0.8
|
||||||
get-intrinsic: 1.3.0
|
get-intrinsic: 1.3.0
|
||||||
|
|
||||||
is-what@4.1.16: {}
|
|
||||||
|
|
||||||
is-wsl@2.2.0:
|
is-wsl@2.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-docker: 2.2.1
|
is-docker: 2.2.1
|
||||||
@@ -12425,8 +12383,6 @@ snapshots:
|
|||||||
mdast-util-to-markdown: 2.1.0
|
mdast-util-to-markdown: 2.1.0
|
||||||
unified: 11.0.5
|
unified: 11.0.5
|
||||||
|
|
||||||
remove-accents@0.4.2: {}
|
|
||||||
|
|
||||||
require-directory@2.1.1: {}
|
require-directory@2.1.1: {}
|
||||||
|
|
||||||
requires-port@1.0.0: {}
|
requires-port@1.0.0: {}
|
||||||
@@ -12767,10 +12723,6 @@ snapshots:
|
|||||||
pirates: 4.0.6
|
pirates: 4.0.6
|
||||||
ts-interface-checker: 0.1.13
|
ts-interface-checker: 0.1.13
|
||||||
|
|
||||||
superjson@1.13.3:
|
|
||||||
dependencies:
|
|
||||||
copy-anything: 3.0.5
|
|
||||||
|
|
||||||
supports-color@5.5.0:
|
supports-color@5.5.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
has-flag: 3.0.0
|
has-flag: 3.0.0
|
||||||
@@ -13108,10 +13060,6 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 18.3.12
|
'@types/react': 18.3.12
|
||||||
|
|
||||||
use-sync-external-store@1.2.0(react@18.3.1):
|
|
||||||
dependencies:
|
|
||||||
react: 18.3.1
|
|
||||||
|
|
||||||
use-sync-external-store@1.4.0(react@18.3.1):
|
use-sync-external-store@1.4.0(react@18.3.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export const createChat = (queryClient: QueryClient) => {
|
|||||||
return {
|
return {
|
||||||
mutationFn: API.createChat,
|
mutationFn: API.createChat,
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(["chats"]);
|
await queryClient.invalidateQueries({ queryKey: ["chats"] });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export const health = () => ({
|
|||||||
export const refreshHealth = (queryClient: QueryClient) => {
|
export const refreshHealth = (queryClient: QueryClient) => {
|
||||||
return {
|
return {
|
||||||
mutationFn: async () => {
|
mutationFn: async () => {
|
||||||
await queryClient.cancelQueries(HEALTH_QUERY_KEY);
|
await queryClient.cancelQueries({ queryKey: HEALTH_QUERY_KEY });
|
||||||
const newHealthData = await API.getHealth(true);
|
const newHealthData = await API.getHealth(true);
|
||||||
queryClient.setQueryData(HEALTH_QUERY_KEY, newHealthData);
|
queryClient.setQueryData(HEALTH_QUERY_KEY, newHealthData);
|
||||||
},
|
},
|
||||||
@@ -38,7 +38,7 @@ export const updateHealthSettings = (
|
|||||||
return {
|
return {
|
||||||
mutationFn: API.updateHealthSettings,
|
mutationFn: API.updateHealthSettings,
|
||||||
onSuccess: async (_, newSettings) => {
|
onSuccess: async (_, newSettings) => {
|
||||||
await queryClient.invalidateQueries(HEALTH_QUERY_KEY);
|
await queryClient.invalidateQueries({ queryKey: HEALTH_QUERY_KEY });
|
||||||
queryClient.setQueryData(HEALTH_QUERY_SETTINGS_KEY, newSettings);
|
queryClient.setQueryData(HEALTH_QUERY_SETTINGS_KEY, newSettings);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -37,7 +37,9 @@ export const exchangeExternalAuthDevice = (
|
|||||||
queryKey: ["external-auth", providerId, "device", deviceCode],
|
queryKey: ["external-auth", providerId, "device", deviceCode],
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
// Force a refresh of the Git auth status.
|
// Force a refresh of the Git auth status.
|
||||||
await queryClient.invalidateQueries(["external-auth", providerId]);
|
await queryClient.invalidateQueries({
|
||||||
|
queryKey: ["external-auth", providerId],
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -57,7 +59,9 @@ export const unlinkExternalAuths = (queryClient: QueryClient) => {
|
|||||||
return {
|
return {
|
||||||
mutationFn: API.unlinkExternalAuthProvider,
|
mutationFn: API.unlinkExternalAuthProvider,
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(["external-auth"]);
|
await queryClient.invalidateQueries({
|
||||||
|
queryKey: ["external-auth"],
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -117,10 +117,12 @@ export const createGroup = (queryClient: QueryClient, organization: string) => {
|
|||||||
mutationFn: (request: CreateGroupRequest) =>
|
mutationFn: (request: CreateGroupRequest) =>
|
||||||
API.createGroup(organization, request),
|
API.createGroup(organization, request),
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(groupsQueryKey);
|
await queryClient.invalidateQueries({
|
||||||
await queryClient.invalidateQueries(
|
queryKey: groupsQueryKey,
|
||||||
getGroupsByOrganizationQueryKey(organization),
|
});
|
||||||
);
|
await queryClient.invalidateQueries({
|
||||||
|
queryKey: getGroupsByOrganizationQueryKey(organization),
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -169,11 +171,13 @@ const invalidateGroup = (
|
|||||||
groupId: string,
|
groupId: string,
|
||||||
) =>
|
) =>
|
||||||
Promise.all([
|
Promise.all([
|
||||||
queryClient.invalidateQueries(groupsQueryKey),
|
queryClient.invalidateQueries({ queryKey: groupsQueryKey }),
|
||||||
queryClient.invalidateQueries(
|
queryClient.invalidateQueries({
|
||||||
getGroupsByOrganizationQueryKey(organization),
|
queryKey: getGroupsByOrganizationQueryKey(organization),
|
||||||
),
|
}),
|
||||||
queryClient.invalidateQueries(getGroupQueryKey(organization, groupId)),
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: getGroupQueryKey(organization, groupId),
|
||||||
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
function sortGroupsByName<T extends Group>(
|
function sortGroupsByName<T extends Group>(
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ export const patchOrganizationSyncSettings = (queryClient: QueryClient) => {
|
|||||||
mutationFn: (request: OrganizationSyncSettings) =>
|
mutationFn: (request: OrganizationSyncSettings) =>
|
||||||
API.patchOrganizationIdpSyncSettings(request),
|
API.patchOrganizationIdpSyncSettings(request),
|
||||||
onSuccess: async () =>
|
onSuccess: async () =>
|
||||||
await queryClient.invalidateQueries(getOrganizationIdpSyncSettingsKey()),
|
await queryClient.invalidateQueries({
|
||||||
|
queryKey: getOrganizationIdpSyncSettingsKey(),
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import {
|
|||||||
type WorkspacePermissions,
|
type WorkspacePermissions,
|
||||||
workspacePermissionChecks,
|
workspacePermissionChecks,
|
||||||
} from "modules/permissions/workspaces";
|
} from "modules/permissions/workspaces";
|
||||||
import type { QueryClient } from "react-query";
|
import type { QueryClient, UseQueryOptions } from "react-query";
|
||||||
import { meKey } from "./users";
|
import { meKey } from "./users";
|
||||||
|
|
||||||
export const createOrganization = (queryClient: QueryClient) => {
|
export const createOrganization = (queryClient: QueryClient) => {
|
||||||
@@ -31,8 +31,8 @@ export const createOrganization = (queryClient: QueryClient) => {
|
|||||||
API.createOrganization(params),
|
API.createOrganization(params),
|
||||||
|
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(meKey);
|
await queryClient.invalidateQueries({ queryKey: meKey });
|
||||||
await queryClient.invalidateQueries(organizationsKey);
|
await queryClient.invalidateQueries({ queryKey: organizationsKey });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -48,7 +48,7 @@ export const updateOrganization = (queryClient: QueryClient) => {
|
|||||||
API.updateOrganization(variables.organizationId, variables.req),
|
API.updateOrganization(variables.organizationId, variables.req),
|
||||||
|
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(organizationsKey);
|
await queryClient.invalidateQueries({ queryKey: organizationsKey });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -59,8 +59,8 @@ export const deleteOrganization = (queryClient: QueryClient) => {
|
|||||||
API.deleteOrganization(organizationId),
|
API.deleteOrganization(organizationId),
|
||||||
|
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(meKey);
|
await queryClient.invalidateQueries({ queryKey: meKey });
|
||||||
await queryClient.invalidateQueries(organizationsKey);
|
await queryClient.invalidateQueries({ queryKey: organizationsKey });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -117,7 +117,9 @@ export const addOrganizationMember = (queryClient: QueryClient, id: string) => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(["organization", id, "members"]);
|
await queryClient.invalidateQueries({
|
||||||
|
queryKey: ["organization", id, "members"],
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -132,7 +134,9 @@ export const removeOrganizationMember = (
|
|||||||
},
|
},
|
||||||
|
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(["organization", id, "members"]);
|
await queryClient.invalidateQueries({
|
||||||
|
queryKey: ["organization", id, "members"],
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -147,11 +151,9 @@ export const updateOrganizationMemberRoles = (
|
|||||||
},
|
},
|
||||||
|
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries([
|
await queryClient.invalidateQueries({
|
||||||
"organization",
|
queryKey: ["organization", organizationId, "members"],
|
||||||
organizationId,
|
});
|
||||||
"members",
|
|
||||||
]);
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -240,9 +242,9 @@ export const patchRoleSyncSettings = (
|
|||||||
mutationFn: (request: RoleSyncSettings) =>
|
mutationFn: (request: RoleSyncSettings) =>
|
||||||
API.patchRoleIdpSyncSettings(request, organization),
|
API.patchRoleIdpSyncSettings(request, organization),
|
||||||
onSuccess: async () =>
|
onSuccess: async () =>
|
||||||
await queryClient.invalidateQueries(
|
await queryClient.invalidateQueries({
|
||||||
getRoleIdpSyncSettingsKey(organization),
|
queryKey: getRoleIdpSyncSettingsKey(organization),
|
||||||
),
|
}),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -269,12 +271,13 @@ export const provisionerJobs = (
|
|||||||
export const organizationsPermissions = (
|
export const organizationsPermissions = (
|
||||||
organizationIds: string[] | undefined,
|
organizationIds: string[] | undefined,
|
||||||
) => {
|
) => {
|
||||||
if (!organizationIds) {
|
|
||||||
return { enabled: false };
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
queryKey: ["organizations", [...organizationIds.sort()], "permissions"],
|
enabled: !!organizationIds,
|
||||||
|
queryKey: [
|
||||||
|
"organizations",
|
||||||
|
[...(organizationIds ?? []).sort()],
|
||||||
|
"permissions",
|
||||||
|
],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
// Only request what we need for the sidebar, which is one edit permission
|
// Only request what we need for the sidebar, which is one edit permission
|
||||||
// per sub-link (settings, groups, roles, and members pages) that tells us
|
// per sub-link (settings, groups, roles, and members pages) that tells us
|
||||||
@@ -283,7 +286,7 @@ export const organizationsPermissions = (
|
|||||||
|
|
||||||
// The endpoint takes a flat array, so to avoid collisions prepend each
|
// The endpoint takes a flat array, so to avoid collisions prepend each
|
||||||
// check with the org ID (the key can be anything we want).
|
// check with the org ID (the key can be anything we want).
|
||||||
const prefixedChecks = organizationIds.flatMap((orgId) =>
|
const prefixedChecks = (organizationIds ?? []).flatMap((orgId) =>
|
||||||
Object.entries(organizationPermissionChecks(orgId)).map(
|
Object.entries(organizationPermissionChecks(orgId)).map(
|
||||||
([key, val]) => [`${orgId}.${key}`, val],
|
([key, val]) => [`${orgId}.${key}`, val],
|
||||||
),
|
),
|
||||||
@@ -315,14 +318,15 @@ export const workspacePermissionsByOrganization = (
|
|||||||
organizationIds: string[] | undefined,
|
organizationIds: string[] | undefined,
|
||||||
userId: string,
|
userId: string,
|
||||||
) => {
|
) => {
|
||||||
if (!organizationIds) {
|
|
||||||
return { enabled: false };
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
queryKey: ["workspaces", [...organizationIds.sort()], "permissions"],
|
enabled: !!organizationIds,
|
||||||
|
queryKey: [
|
||||||
|
"workspaces",
|
||||||
|
[...(organizationIds ?? []).sort()],
|
||||||
|
"permissions",
|
||||||
|
],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const prefixedChecks = organizationIds.flatMap((orgId) =>
|
const prefixedChecks = (organizationIds ?? []).flatMap((orgId) =>
|
||||||
Object.entries(workspacePermissionChecks(orgId, userId)).map(
|
Object.entries(workspacePermissionChecks(orgId, userId)).map(
|
||||||
([key, val]) => [`${orgId}.${key}`, val],
|
([key, val]) => [`${orgId}.${key}`, val],
|
||||||
),
|
),
|
||||||
@@ -346,7 +350,7 @@ export const workspacePermissionsByOrganization = (
|
|||||||
{} as Record<string, Partial<WorkspacePermissions>>,
|
{} as Record<string, Partial<WorkspacePermissions>>,
|
||||||
) as Record<string, WorkspacePermissions>;
|
) as Record<string, WorkspacePermissions>;
|
||||||
},
|
},
|
||||||
};
|
} satisfies UseQueryOptions<Record<string, WorkspacePermissions>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getOrganizationIdpSyncClaimFieldValuesKey = (
|
const getOrganizationIdpSyncClaimFieldValuesKey = (
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ export const createOrganizationRole = (
|
|||||||
mutationFn: (request: Role) =>
|
mutationFn: (request: Role) =>
|
||||||
API.createOrganizationRole(organization, request),
|
API.createOrganizationRole(organization, request),
|
||||||
onSuccess: async (updatedRole: Role) =>
|
onSuccess: async (updatedRole: Role) =>
|
||||||
await queryClient.invalidateQueries(
|
await queryClient.invalidateQueries({
|
||||||
getRoleQueryKey(organization, updatedRole.name),
|
queryKey: getRoleQueryKey(organization, updatedRole.name),
|
||||||
),
|
}),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -47,9 +47,9 @@ export const updateOrganizationRole = (
|
|||||||
mutationFn: (request: Role) =>
|
mutationFn: (request: Role) =>
|
||||||
API.updateOrganizationRole(organization, request),
|
API.updateOrganizationRole(organization, request),
|
||||||
onSuccess: async (updatedRole: Role) =>
|
onSuccess: async (updatedRole: Role) =>
|
||||||
await queryClient.invalidateQueries(
|
await queryClient.invalidateQueries({
|
||||||
getRoleQueryKey(organization, updatedRole.name),
|
queryKey: getRoleQueryKey(organization, updatedRole.name),
|
||||||
),
|
}),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -61,8 +61,8 @@ export const deleteOrganizationRole = (
|
|||||||
mutationFn: (roleName: string) =>
|
mutationFn: (roleName: string) =>
|
||||||
API.deleteOrganizationRole(organization, roleName),
|
API.deleteOrganizationRole(organization, roleName),
|
||||||
onSuccess: async (_: unknown, roleName: string) =>
|
onSuccess: async (_: unknown, roleName: string) =>
|
||||||
await queryClient.invalidateQueries(
|
await queryClient.invalidateQueries({
|
||||||
getRoleQueryKey(organization, roleName),
|
queryKey: getRoleQueryKey(organization, roleName),
|
||||||
),
|
}),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,13 +11,11 @@ const userQuietHoursScheduleKey = (userId: string) => [
|
|||||||
"quietHours",
|
"quietHours",
|
||||||
];
|
];
|
||||||
|
|
||||||
export const userQuietHoursSchedule = (
|
export const userQuietHoursSchedule = (userId: string) => {
|
||||||
userId: string,
|
|
||||||
): QueryOptions<UserQuietHoursScheduleResponse> => {
|
|
||||||
return {
|
return {
|
||||||
queryKey: userQuietHoursScheduleKey(userId),
|
queryKey: userQuietHoursScheduleKey(userId),
|
||||||
queryFn: () => API.getUserQuietHoursSchedule(userId),
|
queryFn: () => API.getUserQuietHoursSchedule(userId),
|
||||||
};
|
} satisfies QueryOptions<UserQuietHoursScheduleResponse>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updateUserQuietHoursSchedule = (
|
export const updateUserQuietHoursSchedule = (
|
||||||
@@ -28,7 +26,9 @@ export const updateUserQuietHoursSchedule = (
|
|||||||
mutationFn: (request: UpdateUserQuietHoursScheduleRequest) =>
|
mutationFn: (request: UpdateUserQuietHoursScheduleRequest) =>
|
||||||
API.updateUserQuietHoursSchedule(userId, request),
|
API.updateUserQuietHoursSchedule(userId, request),
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(userQuietHoursScheduleKey(userId));
|
await queryClient.invalidateQueries({
|
||||||
|
queryKey: userQuietHoursScheduleKey(userId),
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ import { getTemplateVersionFiles } from "utils/templateVersion";
|
|||||||
|
|
||||||
const templateKey = (templateId: string) => ["template", templateId];
|
const templateKey = (templateId: string) => ["template", templateId];
|
||||||
|
|
||||||
export const template = (templateId: string): QueryOptions<Template> => {
|
export const template = (templateId: string) => {
|
||||||
return {
|
return {
|
||||||
queryKey: templateKey(templateId),
|
queryKey: templateKey(templateId),
|
||||||
queryFn: async () => API.getTemplate(templateId),
|
queryFn: async () => API.getTemplate(templateId),
|
||||||
};
|
} satisfies QueryOptions<Template>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const templateByNameKey = (organization: string, name: string) => [
|
export const templateByNameKey = (organization: string, name: string) => [
|
||||||
@@ -28,14 +28,11 @@ export const templateByNameKey = (organization: string, name: string) => [
|
|||||||
name,
|
name,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const templateByName = (
|
export const templateByName = (organization: string, name: string) => {
|
||||||
organization: string,
|
|
||||||
name: string,
|
|
||||||
): QueryOptions<Template> => {
|
|
||||||
return {
|
return {
|
||||||
queryKey: templateByNameKey(organization, name),
|
queryKey: templateByNameKey(organization, name),
|
||||||
queryFn: async () => API.getTemplateByName(organization, name),
|
queryFn: async () => API.getTemplateByName(organization, name),
|
||||||
};
|
} satisfies QueryOptions<Template>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTemplatesQueryKey = (
|
const getTemplatesQueryKey = (
|
||||||
@@ -88,7 +85,9 @@ export const setUserRole = (
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
onSuccess: async (_res, { templateId }) => {
|
onSuccess: async (_res, { templateId }) => {
|
||||||
await queryClient.invalidateQueries(["templateAcl", templateId]);
|
await queryClient.invalidateQueries({
|
||||||
|
queryKey: ["templateAcl", templateId],
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -108,7 +107,9 @@ export const setGroupRole = (
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
onSuccess: async (_res, { templateId }) => {
|
onSuccess: async (_res, { templateId }) => {
|
||||||
await queryClient.invalidateQueries(["templateAcl", templateId]);
|
await queryClient.invalidateQueries({
|
||||||
|
queryKey: ["templateAcl", templateId],
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -197,9 +198,9 @@ export const updateActiveTemplateVersion = (
|
|||||||
}),
|
}),
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
// invalidated because of `active_version_id`
|
// invalidated because of `active_version_id`
|
||||||
await queryClient.invalidateQueries(
|
await queryClient.invalidateQueries({
|
||||||
templateByNameKey(template.organization_id, template.name),
|
queryKey: templateByNameKey(template.organization_id, template.name),
|
||||||
);
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export const users = (req: UsersRequest): UseQueryOptions<GetUsersResponse> => {
|
|||||||
return {
|
return {
|
||||||
queryKey: usersKey(req),
|
queryKey: usersKey(req),
|
||||||
queryFn: ({ signal }) => API.getUsers(req, signal),
|
queryFn: ({ signal }) => API.getUsers(req, signal),
|
||||||
cacheTime: 5 * 1000 * 60,
|
gcTime: 5 * 1000 * 60,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ export const createUser = (queryClient: QueryClient) => {
|
|||||||
return {
|
return {
|
||||||
mutationFn: API.createUser,
|
mutationFn: API.createUser,
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(["users"]);
|
await queryClient.invalidateQueries({ queryKey: ["users"] });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -84,7 +84,7 @@ export const suspendUser = (queryClient: QueryClient) => {
|
|||||||
return {
|
return {
|
||||||
mutationFn: API.suspendUser,
|
mutationFn: API.suspendUser,
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(["users"]);
|
await queryClient.invalidateQueries({ queryKey: ["users"] });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -93,7 +93,7 @@ export const activateUser = (queryClient: QueryClient) => {
|
|||||||
return {
|
return {
|
||||||
mutationFn: API.activateUser,
|
mutationFn: API.activateUser,
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(["users"]);
|
await queryClient.invalidateQueries({ queryKey: ["users"] });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -102,7 +102,7 @@ export const deleteUser = (queryClient: QueryClient) => {
|
|||||||
return {
|
return {
|
||||||
mutationFn: API.deleteUser,
|
mutationFn: API.deleteUser,
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(["users"]);
|
await queryClient.invalidateQueries({ queryKey: ["users"] });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -112,7 +112,7 @@ export const updateRoles = (queryClient: QueryClient) => {
|
|||||||
mutationFn: ({ userId, roles }: { userId: string; roles: string[] }) =>
|
mutationFn: ({ userId, roles }: { userId: string; roles: string[] }) =>
|
||||||
API.updateUserRoles(roles, userId),
|
API.updateUserRoles(roles, userId),
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(["users"]);
|
await queryClient.invalidateQueries({ queryKey: ["users"] });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -257,7 +257,9 @@ export const updateAppearanceSettings = (
|
|||||||
onSuccess: async () =>
|
onSuccess: async () =>
|
||||||
// Could technically invalidate more, but we only ever care about the
|
// Could technically invalidate more, but we only ever care about the
|
||||||
// `theme_preference` for the `me` query.
|
// `theme_preference` for the `me` query.
|
||||||
await queryClient.invalidateQueries(myAppearanceKey),
|
await queryClient.invalidateQueries({
|
||||||
|
queryKey: myAppearanceKey,
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ import type { MetadataState, MetadataValue } from "hooks/useEmbeddedMetadata";
|
|||||||
import type { QueryKey, UseQueryOptions } from "react-query";
|
import type { QueryKey, UseQueryOptions } from "react-query";
|
||||||
|
|
||||||
export const disabledRefetchOptions = {
|
export const disabledRefetchOptions = {
|
||||||
cacheTime: Number.POSITIVE_INFINITY,
|
gcTime: Number.POSITIVE_INFINITY,
|
||||||
staleTime: Number.POSITIVE_INFINITY,
|
staleTime: Number.POSITIVE_INFINITY,
|
||||||
refetchOnMount: false,
|
refetchOnMount: false,
|
||||||
refetchOnReconnect: false,
|
refetchOnReconnect: false,
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
} as const satisfies UseQueryOptions;
|
} as const satisfies Partial<UseQueryOptions>;
|
||||||
|
|
||||||
type UseQueryOptionsWithMetadata<
|
type UseQueryOptionsWithMetadata<
|
||||||
TMetadata extends MetadataValue = MetadataValue,
|
TMetadata extends MetadataValue = MetadataValue,
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export const workspaceBuildsKey = (workspaceId: string) => [
|
|||||||
export const infiniteWorkspaceBuilds = (
|
export const infiniteWorkspaceBuilds = (
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
req?: WorkspaceBuildsRequest,
|
req?: WorkspaceBuildsRequest,
|
||||||
): UseInfiniteQueryOptions<WorkspaceBuild[]> => {
|
) => {
|
||||||
const limit = req?.limit ?? 25;
|
const limit = req?.limit ?? 25;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -48,13 +48,17 @@ export const infiniteWorkspaceBuilds = (
|
|||||||
}
|
}
|
||||||
return pages.length + 1;
|
return pages.length + 1;
|
||||||
},
|
},
|
||||||
queryFn: ({ pageParam = 0 }) => {
|
initialPageParam: 0,
|
||||||
|
queryFn: ({ pageParam }) => {
|
||||||
|
if (typeof pageParam !== "number") {
|
||||||
|
throw new Error("pageParam must be a number");
|
||||||
|
}
|
||||||
return API.getWorkspaceBuilds(workspaceId, {
|
return API.getWorkspaceBuilds(workspaceId, {
|
||||||
limit,
|
limit,
|
||||||
offset: pageParam <= 0 ? 0 : (pageParam - 1) * limit,
|
offset: pageParam <= 0 ? 0 : (pageParam - 1) * limit,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
} satisfies UseInfiniteQueryOptions<WorkspaceBuild[]>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// We use readyAgentsCount to invalidate the query when an agent connects
|
// We use readyAgentsCount to invalidate the query when an agent connects
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export const createWorkspace = (queryClient: QueryClient) => {
|
|||||||
return API.createWorkspace(userId, req);
|
return API.createWorkspace(userId, req);
|
||||||
},
|
},
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(["workspaces"]);
|
await queryClient.invalidateQueries({ queryKey: ["workspaces"] });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -114,7 +114,7 @@ export const autoCreateWorkspace = (queryClient: QueryClient) => {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(["workspaces"]);
|
await queryClient.invalidateQueries({ queryKey: ["workspaces"] });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { SelectFilterOption } from "components/Filter/SelectFilter";
|
import type { SelectFilterOption } from "components/Filter/SelectFilter";
|
||||||
import { useMemo, useRef, useState } from "react";
|
import { useMemo, useRef, useState } from "react";
|
||||||
import { useQuery } from "react-query";
|
import { keepPreviousData, useQuery } from "react-query";
|
||||||
|
|
||||||
export type UseFilterMenuOptions = {
|
export type UseFilterMenuOptions = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -40,7 +40,7 @@ export const useFilterMenu = ({
|
|||||||
return getSelectedOption();
|
return getSelectedOption();
|
||||||
},
|
},
|
||||||
enabled,
|
enabled,
|
||||||
keepPreviousData: true,
|
placeholderData: keepPreviousData,
|
||||||
});
|
});
|
||||||
const selectedOption = selectedOptionQuery.data;
|
const selectedOption = selectedOptionQuery.data;
|
||||||
const searchOptionsQuery = useQuery({
|
const searchOptionsQuery = useQuery({
|
||||||
|
|||||||
@@ -29,24 +29,26 @@ export const OrganizationAutocomplete: FC<OrganizationAutocompleteProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [selected, setSelected] = useState<Organization | null>(null);
|
const [selected, setSelected] = useState<Organization | null>(null);
|
||||||
|
|
||||||
const organizationsQuery = useQuery(organizations());
|
const organizationsQuery = useQuery(organizations());
|
||||||
|
const checks =
|
||||||
|
check &&
|
||||||
|
organizationsQuery.data &&
|
||||||
|
Object.fromEntries(
|
||||||
|
organizationsQuery.data.map((org) => [
|
||||||
|
org.id,
|
||||||
|
{
|
||||||
|
...check,
|
||||||
|
object: { ...check.object, organization_id: org.id },
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
const permissionsQuery = useQuery(
|
const permissionsQuery = useQuery({
|
||||||
check && organizationsQuery.data
|
...checkAuthorization({
|
||||||
? checkAuthorization({
|
checks: checks ?? {},
|
||||||
checks: Object.fromEntries(
|
}),
|
||||||
organizationsQuery.data.map((org) => [
|
enabled: Boolean(check && organizationsQuery.data),
|
||||||
org.id,
|
});
|
||||||
{
|
|
||||||
...check,
|
|
||||||
object: { ...check.object, organization_id: org.id },
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
})
|
|
||||||
: { enabled: false },
|
|
||||||
);
|
|
||||||
|
|
||||||
// If an authorization check was provided, filter the organizations based on
|
// If an authorization check was provided, filter the organizations based on
|
||||||
// the results of that check.
|
// the results of that check.
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import type { PaginationResult } from "./PaginationContainer";
|
|||||||
|
|
||||||
type ResultBase = Omit<
|
type ResultBase = Omit<
|
||||||
PaginationResult,
|
PaginationResult,
|
||||||
"isPreviousData" | "currentOffsetStart" | "totalRecords" | "totalPages"
|
"isPlaceholderData" | "currentOffsetStart" | "totalRecords" | "totalPages"
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export const mockPaginationResultBase: ResultBase = {
|
export const mockPaginationResultBase: ResultBase = {
|
||||||
@@ -27,7 +27,7 @@ export const mockPaginationResultBase: ResultBase = {
|
|||||||
export const mockInitialRenderResult: PaginationResult = {
|
export const mockInitialRenderResult: PaginationResult = {
|
||||||
...mockPaginationResultBase,
|
...mockPaginationResultBase,
|
||||||
isSuccess: false,
|
isSuccess: false,
|
||||||
isPreviousData: false,
|
isPlaceholderData: false,
|
||||||
currentOffsetStart: undefined,
|
currentOffsetStart: undefined,
|
||||||
hasNextPage: false,
|
hasNextPage: false,
|
||||||
hasPreviousPage: false,
|
hasPreviousPage: false,
|
||||||
@@ -38,7 +38,7 @@ export const mockInitialRenderResult: PaginationResult = {
|
|||||||
export const mockSuccessResult: PaginationResult = {
|
export const mockSuccessResult: PaginationResult = {
|
||||||
...mockPaginationResultBase,
|
...mockPaginationResultBase,
|
||||||
isSuccess: true,
|
isSuccess: true,
|
||||||
isPreviousData: false,
|
isPlaceholderData: false,
|
||||||
currentOffsetStart: 1,
|
currentOffsetStart: 1,
|
||||||
totalPages: 1,
|
totalPages: 1,
|
||||||
totalRecords: 4,
|
totalRecords: 4,
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export const FirstPageWithData: Story = {
|
|||||||
totalPages: 4,
|
totalPages: 4,
|
||||||
hasPreviousPage: false,
|
hasPreviousPage: false,
|
||||||
hasNextPage: true,
|
hasNextPage: true,
|
||||||
isPreviousData: false,
|
isPlaceholderData: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -65,7 +65,7 @@ export const FirstPageWithLittleData: Story = {
|
|||||||
totalPages: 1,
|
totalPages: 1,
|
||||||
hasPreviousPage: false,
|
hasPreviousPage: false,
|
||||||
hasNextPage: false,
|
hasNextPage: false,
|
||||||
isPreviousData: false,
|
isPlaceholderData: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -81,7 +81,7 @@ export const FirstPageWithNoData: Story = {
|
|||||||
totalPages: 0,
|
totalPages: 0,
|
||||||
hasPreviousPage: false,
|
hasPreviousPage: false,
|
||||||
hasNextPage: false,
|
hasNextPage: false,
|
||||||
isPreviousData: false,
|
isPlaceholderData: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -97,7 +97,7 @@ export const TransitionFromFirstToSecondPage: Story = {
|
|||||||
totalPages: 4,
|
totalPages: 4,
|
||||||
hasPreviousPage: false,
|
hasPreviousPage: false,
|
||||||
hasNextPage: false,
|
hasNextPage: false,
|
||||||
isPreviousData: true,
|
isPlaceholderData: true,
|
||||||
},
|
},
|
||||||
children: <div>Previous data from page 1</div>,
|
children: <div>Previous data from page 1</div>,
|
||||||
},
|
},
|
||||||
@@ -114,7 +114,7 @@ export const SecondPageWithData: Story = {
|
|||||||
totalPages: 4,
|
totalPages: 4,
|
||||||
hasPreviousPage: true,
|
hasPreviousPage: true,
|
||||||
hasNextPage: true,
|
hasNextPage: true,
|
||||||
isPreviousData: false,
|
isPlaceholderData: false,
|
||||||
},
|
},
|
||||||
children: <div>New data for page 2</div>,
|
children: <div>New data for page 2</div>,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { PaginationHeader } from "./PaginationHeader";
|
|||||||
import { PaginationWidgetBase } from "./PaginationWidgetBase";
|
import { PaginationWidgetBase } from "./PaginationWidgetBase";
|
||||||
|
|
||||||
export type PaginationResult = PaginationResultInfo & {
|
export type PaginationResult = PaginationResultInfo & {
|
||||||
isPreviousData: boolean;
|
isPlaceholderData: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type PaginationProps = HTMLAttributes<HTMLDivElement> & {
|
type PaginationProps = HTMLAttributes<HTMLDivElement> & {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import TextField, { type TextFieldProps } from "@mui/material/TextField";
|
|||||||
import { API } from "api/api";
|
import { API } from "api/api";
|
||||||
import { useDebouncedValue } from "hooks/debounce";
|
import { useDebouncedValue } from "hooks/debounce";
|
||||||
import type { FC } from "react";
|
import type { FC } from "react";
|
||||||
import { useQuery } from "react-query";
|
import { keepPreviousData, useQuery } from "react-query";
|
||||||
|
|
||||||
// TODO: @BrunoQuaresma: Unable to integrate Yup + Formik for validation. The
|
// TODO: @BrunoQuaresma: Unable to integrate Yup + Formik for validation. The
|
||||||
// validation was triggering on the onChange event, but the form.errors were not
|
// validation was triggering on the onChange event, but the form.errors were not
|
||||||
@@ -19,7 +19,7 @@ export const PasswordField: FC<TextFieldProps> = (props) => {
|
|||||||
const validatePasswordQuery = useQuery({
|
const validatePasswordQuery = useQuery({
|
||||||
queryKey: ["validatePassword", debouncedValue],
|
queryKey: ["validatePassword", debouncedValue],
|
||||||
queryFn: () => API.validateUserPassword(debouncedValue),
|
queryFn: () => API.validateUserPassword(debouncedValue),
|
||||||
keepPreviousData: true,
|
placeholderData: keepPreviousData,
|
||||||
enabled: debouncedValue.length > 0,
|
enabled: debouncedValue.length > 0,
|
||||||
});
|
});
|
||||||
const valid = validatePasswordQuery.data?.valid ?? true;
|
const valid = validatePasswordQuery.data?.valid ?? true;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
type FC,
|
type FC,
|
||||||
useState,
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { useQuery } from "react-query";
|
import { keepPreviousData, useQuery } from "react-query";
|
||||||
import { prepareQuery } from "utils/filters";
|
import { prepareQuery } from "utils/filters";
|
||||||
|
|
||||||
// The common properties between users and org members that we need.
|
// The common properties between users and org members that we need.
|
||||||
@@ -45,7 +45,7 @@ export const UserAutocomplete: FC<UserAutocompleteProps> = (props) => {
|
|||||||
limit: 25,
|
limit: 25,
|
||||||
}),
|
}),
|
||||||
enabled: filter !== undefined,
|
enabled: filter !== undefined,
|
||||||
keepPreviousData: true,
|
placeholderData: keepPreviousData,
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<InnerAutocomplete<User>
|
<InnerAutocomplete<User>
|
||||||
@@ -72,7 +72,7 @@ export const MemberAutocomplete: FC<MemberAutocompleteProps> = ({
|
|||||||
const membersQuery = useQuery({
|
const membersQuery = useQuery({
|
||||||
...organizationMembers(organizationId),
|
...organizationMembers(organizationId),
|
||||||
enabled: filter !== undefined,
|
enabled: filter !== undefined,
|
||||||
keepPreviousData: true,
|
placeholderData: keepPreviousData,
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<InnerAutocomplete<OrganizationMemberWithUserData>
|
<InnerAutocomplete<OrganizationMemberWithUserData>
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export const AuthProvider: FC<PropsWithChildren> = ({ children }) => {
|
|||||||
userQuery.isError &&
|
userQuery.isError &&
|
||||||
isApiError(userQuery.error) &&
|
isApiError(userQuery.error) &&
|
||||||
userQuery.error.response.status === 401;
|
userQuery.error.response.status === 401;
|
||||||
const isSigningOut = logoutMutation.isLoading;
|
const isSigningOut = logoutMutation.isPending;
|
||||||
const isLoading =
|
const isLoading =
|
||||||
userQuery.isLoading ||
|
userQuery.isLoading ||
|
||||||
hasFirstUserQuery.isLoading ||
|
hasFirstUserQuery.isLoading ||
|
||||||
@@ -80,8 +80,8 @@ export const AuthProvider: FC<PropsWithChildren> = ({ children }) => {
|
|||||||
const isConfiguringTheFirstUser =
|
const isConfiguringTheFirstUser =
|
||||||
!hasFirstUserQuery.isLoading && !hasFirstUserQuery.data;
|
!hasFirstUserQuery.isLoading && !hasFirstUserQuery.data;
|
||||||
const isSignedIn = userQuery.isSuccess && userQuery.data !== undefined;
|
const isSignedIn = userQuery.isSuccess && userQuery.data !== undefined;
|
||||||
const isSigningIn = loginMutation.isLoading;
|
const isSigningIn = loginMutation.isPending;
|
||||||
const isUpdatingProfile = updateProfileMutation.isLoading;
|
const isUpdatingProfile = updateProfileMutation.isPending;
|
||||||
|
|
||||||
const signOut = useCallback(() => {
|
const signOut = useCallback(() => {
|
||||||
logoutMutation.mutate();
|
logoutMutation.mutate();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
type QueryKey,
|
type QueryKey,
|
||||||
type UseQueryOptions,
|
type UseQueryOptions,
|
||||||
type UseQueryResult,
|
type UseQueryResult,
|
||||||
|
keepPreviousData,
|
||||||
useQuery,
|
useQuery,
|
||||||
useQueryClient,
|
useQueryClient,
|
||||||
} from "react-query";
|
} from "react-query";
|
||||||
@@ -140,7 +141,7 @@ export function usePaginatedQuery<
|
|||||||
const query = useQuery<TQueryFnData, TError, TData, TQueryKey>({
|
const query = useQuery<TQueryFnData, TError, TData, TQueryKey>({
|
||||||
...extraOptions,
|
...extraOptions,
|
||||||
...getQueryOptionsFromPage(currentPage),
|
...getQueryOptionsFromPage(currentPage),
|
||||||
keepPreviousData: true,
|
placeholderData: keepPreviousData,
|
||||||
});
|
});
|
||||||
|
|
||||||
const totalRecords = query.data?.count;
|
const totalRecords = query.data?.count;
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export const NotificationsInbox: FC<NotificationsInboxProps> = ({
|
|||||||
res: ListInboxNotificationsResponse,
|
res: ListInboxNotificationsResponse,
|
||||||
) => ListInboxNotificationsResponse,
|
) => ListInboxNotificationsResponse,
|
||||||
) => {
|
) => {
|
||||||
await queryClient.cancelQueries(NOTIFICATIONS_QUERY_KEY);
|
await queryClient.cancelQueries({ queryKey: NOTIFICATIONS_QUERY_KEY });
|
||||||
queryClient.setQueryData<ListInboxNotificationsResponse>(
|
queryClient.setQueryData<ListInboxNotificationsResponse>(
|
||||||
NOTIFICATIONS_QUERY_KEY,
|
NOTIFICATIONS_QUERY_KEY,
|
||||||
(prev) => {
|
(prev) => {
|
||||||
@@ -90,7 +90,7 @@ export const NotificationsInbox: FC<NotificationsInboxProps> = ({
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
mutate: loadMoreNotifications,
|
mutate: loadMoreNotifications,
|
||||||
isLoading: isLoadingMoreNotifications,
|
isPending: isLoadingMoreNotifications,
|
||||||
} = useMutation({
|
} = useMutation({
|
||||||
mutationFn: async () => {
|
mutationFn: async () => {
|
||||||
if (!inboxRes || inboxRes.notifications.length === 0) {
|
if (!inboxRes || inboxRes.notifications.length === 0) {
|
||||||
|
|||||||
@@ -157,8 +157,8 @@ export const AgentRow: FC<AgentRowProps> = ({
|
|||||||
select: (res) => res.containers.filter((c) => c.status === "running"),
|
select: (res) => res.containers.filter((c) => c.status === "running"),
|
||||||
// TODO: Implement a websocket connection to get updates on containers
|
// TODO: Implement a websocket connection to get updates on containers
|
||||||
// without having to poll.
|
// without having to poll.
|
||||||
refetchInterval: (_, query) => {
|
refetchInterval: ({ state }) => {
|
||||||
const { error } = query.state;
|
const { error } = state;
|
||||||
return isAxiosError(error) && error.response?.status === 403
|
return isAxiosError(error) && error.response?.status === 403
|
||||||
? false
|
? false
|
||||||
: 10_000;
|
: 10_000;
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ export const PortForwardPopoverView: FC<PortForwardPopoverViewProps> = ({
|
|||||||
// share port form
|
// share port form
|
||||||
const {
|
const {
|
||||||
mutateAsync: upsertWorkspacePortShareForm,
|
mutateAsync: upsertWorkspacePortShareForm,
|
||||||
isLoading: isSubmitting,
|
isPending: isSubmitting,
|
||||||
error: submitError,
|
error: submitError,
|
||||||
} = useMutation(upsertWorkspacePortShare(workspaceID));
|
} = useMutation(upsertWorkspacePortShare(workspaceID));
|
||||||
const validationSchema = getValidationSchema();
|
const validationSchema = getValidationSchema();
|
||||||
|
|||||||
@@ -34,11 +34,10 @@ function getDuplicationUrlParams(
|
|||||||
export function useWorkspaceDuplication(workspace?: Workspace) {
|
export function useWorkspaceDuplication(workspace?: Workspace) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const getLink = useLinks();
|
const getLink = useLinks();
|
||||||
const buildParametersQuery = useQuery(
|
const buildParametersQuery = useQuery({
|
||||||
workspace !== undefined
|
...workspaceBuildParameters(workspace?.latest_build.id ?? ""),
|
||||||
? workspaceBuildParameters(workspace.latest_build.id)
|
enabled: !!workspace,
|
||||||
: { enabled: false },
|
});
|
||||||
);
|
|
||||||
|
|
||||||
// Not using useEffectEvent for this, because useEffect isn't really an
|
// Not using useEffectEvent for this, because useEffect isn't really an
|
||||||
// intended use case for this custom hook
|
// intended use case for this custom hook
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export const useWorkspaceUpdate = ({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
update,
|
update,
|
||||||
isUpdating: updateWorkspaceMutation.isLoading,
|
isUpdating: updateWorkspaceMutation.isPending,
|
||||||
dialogs: {
|
dialogs: {
|
||||||
updateConfirmation: {
|
updateConfirmation: {
|
||||||
open: isConfirmingUpdate,
|
open: isConfirmingUpdate,
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ export const ChatLayout: FC = () => {
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={handleNewChat}
|
onClick={handleNewChat}
|
||||||
disabled={createChatMutation.isLoading}
|
disabled={createChatMutation.isPending}
|
||||||
>
|
>
|
||||||
<PlusIcon />
|
<PlusIcon />
|
||||||
New Chat
|
New Chat
|
||||||
|
|||||||
@@ -221,14 +221,10 @@ export const CreateTemplateForm: FC<CreateTemplateFormProps> = (props) => {
|
|||||||
});
|
});
|
||||||
const getFieldHelpers = getFormHelpers<CreateTemplateFormData>(form, error);
|
const getFieldHelpers = getFormHelpers<CreateTemplateFormData>(form, error);
|
||||||
|
|
||||||
const { data: provisioners } = useQuery(
|
const { data: provisioners } = useQuery({
|
||||||
selectedOrg
|
...provisionerDaemons(selectedOrg?.id ?? ""),
|
||||||
? {
|
enabled: showOrganizationPicker && !!selectedOrg,
|
||||||
...provisionerDaemons(selectedOrg.id),
|
});
|
||||||
enabled: showOrganizationPicker,
|
|
||||||
}
|
|
||||||
: { enabled: false },
|
|
||||||
);
|
|
||||||
|
|
||||||
// TODO: Ideally, we would have a backend endpoint that could notify the
|
// TODO: Ideally, we would have a backend endpoint that could notify the
|
||||||
// frontend that a provisioner has been connected, so that we could hide
|
// frontend that a provisioner has been connected, so that we could hide
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ const CreateTemplatePage: FC = () => {
|
|||||||
},
|
},
|
||||||
onOpenBuildLogsDrawer: () => setIsBuildLogsOpen(true),
|
onOpenBuildLogsDrawer: () => setIsBuildLogsOpen(true),
|
||||||
error: createTemplateMutation.error,
|
error: createTemplateMutation.error,
|
||||||
isCreating: createTemplateMutation.isLoading,
|
isCreating: createTemplateMutation.isPending,
|
||||||
variablesSectionRef,
|
variablesSectionRef,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
templateVersionLogs,
|
templateVersionLogs,
|
||||||
templateVersionVariables,
|
templateVersionVariables,
|
||||||
} from "api/queries/templates";
|
} from "api/queries/templates";
|
||||||
|
import type { Template, TemplateVersion } from "api/typesGenerated";
|
||||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||||
import { Loader } from "components/Loader/Loader";
|
import { Loader } from "components/Loader/Loader";
|
||||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||||
@@ -25,7 +26,9 @@ export const DuplicateTemplateView: FC<CreateTemplatePageViewProps> = ({
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { entitlements } = useDashboard();
|
const { entitlements } = useDashboard();
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const templateQuery = useQuery(template(searchParams.get("fromTemplate")!));
|
const templateQuery = useQuery(
|
||||||
|
template(searchParams.get("fromTemplate") as string),
|
||||||
|
);
|
||||||
const activeVersionId = templateQuery.data?.active_version_id ?? "";
|
const activeVersionId = templateQuery.data?.active_version_id ?? "";
|
||||||
const templateVersionQuery = useQuery({
|
const templateVersionQuery = useQuery({
|
||||||
...templateVersion(activeVersionId),
|
...templateVersion(activeVersionId),
|
||||||
@@ -65,7 +68,7 @@ export const DuplicateTemplateView: FC<CreateTemplatePageViewProps> = ({
|
|||||||
{...formPermissions}
|
{...formPermissions}
|
||||||
variablesSectionRef={variablesSectionRef}
|
variablesSectionRef={variablesSectionRef}
|
||||||
onOpenBuildLogsDrawer={onOpenBuildLogsDrawer}
|
onOpenBuildLogsDrawer={onOpenBuildLogsDrawer}
|
||||||
copiedTemplate={templateQuery.data!}
|
copiedTemplate={templateQuery.data as Template}
|
||||||
error={error}
|
error={error}
|
||||||
isSubmitting={isCreating}
|
isSubmitting={isCreating}
|
||||||
variables={templateVersionVariablesQuery.data}
|
variables={templateVersionVariablesQuery.data}
|
||||||
@@ -74,9 +77,9 @@ export const DuplicateTemplateView: FC<CreateTemplatePageViewProps> = ({
|
|||||||
logs={templateVersionLogsQuery.data}
|
logs={templateVersionLogsQuery.data}
|
||||||
onSubmit={async (formData) => {
|
onSubmit={async (formData) => {
|
||||||
await onCreateTemplate({
|
await onCreateTemplate({
|
||||||
organization: templateQuery.data!.organization_name,
|
organization: (templateQuery.data as Template).organization_name,
|
||||||
version: firstVersionFromFile(
|
version: firstVersionFromFile(
|
||||||
templateVersionQuery.data!.job.file_id,
|
(templateVersionQuery.data as TemplateVersion).job.file_id,
|
||||||
formData.user_variable_values,
|
formData.user_variable_values,
|
||||||
formData.provisioner_type,
|
formData.provisioner_type,
|
||||||
formData.tags,
|
formData.tags,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { ErrorAlert } from "components/Alert/ErrorAlert";
|
|||||||
import { Loader } from "components/Loader/Loader";
|
import { Loader } from "components/Loader/Loader";
|
||||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||||
import type { FC } from "react";
|
import type { FC } from "react";
|
||||||
import { useQuery } from "react-query";
|
import { keepPreviousData, useQuery } from "react-query";
|
||||||
import { useNavigate, useSearchParams } from "react-router-dom";
|
import { useNavigate, useSearchParams } from "react-router-dom";
|
||||||
import { CreateTemplateForm } from "./CreateTemplateForm";
|
import { CreateTemplateForm } from "./CreateTemplateForm";
|
||||||
import type { CreateTemplatePageViewProps } from "./types";
|
import type { CreateTemplatePageViewProps } from "./types";
|
||||||
@@ -46,7 +46,7 @@ export const ImportStarterTemplateView: FC<CreateTemplatePageViewProps> = ({
|
|||||||
|
|
||||||
const missedVariables = useQuery({
|
const missedVariables = useQuery({
|
||||||
...templateVersionVariables(isJobError ? error.version.id : ""),
|
...templateVersionVariables(isJobError ? error.version.id : ""),
|
||||||
keepPreviousData: true,
|
placeholderData: keepPreviousData,
|
||||||
enabled:
|
enabled:
|
||||||
isJobError && error.job.error_code === "REQUIRED_TEMPLATE_VARIABLES",
|
isJobError && error.job.error_code === "REQUIRED_TEMPLATE_VARIABLES",
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export const UploadTemplateView: FC<CreateTemplatePageViewProps> = ({
|
|||||||
uploadFileMutation.reset();
|
uploadFileMutation.reset();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
isUploading: uploadFileMutation.isLoading,
|
isUploading: uploadFileMutation.isPending,
|
||||||
onRemove: uploadFileMutation.reset,
|
onRemove: uploadFileMutation.reset,
|
||||||
file: uploadFileMutation.variables,
|
file: uploadFileMutation.variables,
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -24,11 +24,11 @@ const CreateTokenPage: FC = () => {
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
mutate: saveToken,
|
mutate: saveToken,
|
||||||
isLoading: isCreating,
|
isPending: isCreating,
|
||||||
isError: creationFailed,
|
isError: creationFailed,
|
||||||
isSuccess: creationSuccessful,
|
isSuccess: creationSuccessful,
|
||||||
data: newToken,
|
data: newToken,
|
||||||
} = useMutation(API.createToken);
|
} = useMutation({ mutationFn: API.createToken });
|
||||||
const {
|
const {
|
||||||
data: tokenConfig,
|
data: tokenConfig,
|
||||||
isLoading: fetchingTokenConfig,
|
isLoading: fetchingTokenConfig,
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const CreateUserPage: FC = () => {
|
|||||||
|
|
||||||
<CreateUserForm
|
<CreateUserForm
|
||||||
error={createUserMutation.error}
|
error={createUserMutation.error}
|
||||||
isLoading={createUserMutation.isLoading}
|
isLoading={createUserMutation.isPending}
|
||||||
onSubmit={async (user) => {
|
onSubmit={async (user) => {
|
||||||
await createUserMutation.mutateAsync({
|
await createUserMutation.mutateAsync({
|
||||||
username: user.username,
|
username: user.username,
|
||||||
|
|||||||
@@ -15,44 +15,33 @@ const CreateWorkspaceExperimentRouter: FC = () => {
|
|||||||
|
|
||||||
const { organization: organizationName = "default", template: templateName } =
|
const { organization: organizationName = "default", template: templateName } =
|
||||||
useParams() as { organization?: string; template: string };
|
useParams() as { organization?: string; template: string };
|
||||||
const templateQuery = useQuery(
|
const templateQuery = useQuery({
|
||||||
dynamicParametersEnabled
|
...templateByName(organizationName, templateName),
|
||||||
? templateByName(organizationName, templateName)
|
enabled: dynamicParametersEnabled,
|
||||||
: { enabled: false },
|
});
|
||||||
);
|
|
||||||
|
|
||||||
const optOutQuery = useQuery(
|
const optOutQuery = useQuery({
|
||||||
templateQuery.data
|
enabled: !!templateQuery.data,
|
||||||
? {
|
queryKey: [organizationName, "template", templateQuery.data?.id, "optOut"],
|
||||||
queryKey: [
|
queryFn: () => {
|
||||||
organizationName,
|
const templateId = templateQuery.data?.id;
|
||||||
"template",
|
const localStorageKey = optOutKey(templateId ?? "");
|
||||||
templateQuery.data.id,
|
const storedOptOutString = localStorage.getItem(localStorageKey);
|
||||||
"optOut",
|
|
||||||
],
|
|
||||||
queryFn: () => {
|
|
||||||
const templateId = templateQuery.data.id;
|
|
||||||
const localStorageKey = optOutKey(templateId);
|
|
||||||
const storedOptOutString = localStorage.getItem(localStorageKey);
|
|
||||||
|
|
||||||
let optOutResult: boolean;
|
let optOutResult: boolean;
|
||||||
|
|
||||||
if (storedOptOutString !== null) {
|
if (storedOptOutString !== null) {
|
||||||
optOutResult = storedOptOutString === "true";
|
optOutResult = storedOptOutString === "true";
|
||||||
} else {
|
} else {
|
||||||
optOutResult = Boolean(
|
optOutResult = !!templateQuery.data?.use_classic_parameter_flow;
|
||||||
templateQuery.data.use_classic_parameter_flow,
|
}
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
templateId: templateId,
|
templateId: templateId,
|
||||||
optedOut: optOutResult,
|
optedOut: optOutResult,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
}
|
});
|
||||||
: { enabled: false },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (dynamicParametersEnabled) {
|
if (dynamicParametersEnabled) {
|
||||||
if (optOutQuery.isLoading) {
|
if (optOutQuery.isLoading) {
|
||||||
@@ -63,7 +52,7 @@ const CreateWorkspaceExperimentRouter: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const toggleOptedOut = () => {
|
const toggleOptedOut = () => {
|
||||||
const key = optOutKey(optOutQuery.data.templateId);
|
const key = optOutKey(optOutQuery.data?.templateId ?? "");
|
||||||
const storedValue = localStorage.getItem(key);
|
const storedValue = localStorage.getItem(key);
|
||||||
|
|
||||||
const current = storedValue
|
const current = storedValue
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
} from "api/queries/templates";
|
} from "api/queries/templates";
|
||||||
import { autoCreateWorkspace, createWorkspace } from "api/queries/workspaces";
|
import { autoCreateWorkspace, createWorkspace } from "api/queries/workspaces";
|
||||||
import type {
|
import type {
|
||||||
|
Template,
|
||||||
TemplateVersionParameter,
|
TemplateVersionParameter,
|
||||||
UserParameter,
|
UserParameter,
|
||||||
Workspace,
|
Workspace,
|
||||||
@@ -62,15 +63,14 @@ const CreateWorkspacePage: FC = () => {
|
|||||||
);
|
);
|
||||||
const templateVersionPresetsQuery = useQuery({
|
const templateVersionPresetsQuery = useQuery({
|
||||||
...templateVersionPresets(templateQuery.data?.active_version_id ?? ""),
|
...templateVersionPresets(templateQuery.data?.active_version_id ?? ""),
|
||||||
enabled: templateQuery.data !== undefined,
|
enabled: !!templateQuery.data,
|
||||||
|
});
|
||||||
|
const permissionsQuery = useQuery({
|
||||||
|
...checkAuthorization({
|
||||||
|
checks: createWorkspaceChecks(templateQuery.data?.organization_id ?? ""),
|
||||||
|
}),
|
||||||
|
enabled: !!templateQuery.data,
|
||||||
});
|
});
|
||||||
const permissionsQuery = useQuery(
|
|
||||||
templateQuery.data
|
|
||||||
? checkAuthorization({
|
|
||||||
checks: createWorkspaceChecks(templateQuery.data.organization_id),
|
|
||||||
})
|
|
||||||
: { enabled: false },
|
|
||||||
);
|
|
||||||
const realizedVersionId =
|
const realizedVersionId =
|
||||||
customVersionId ?? templateQuery.data?.active_version_id;
|
customVersionId ?? templateQuery.data?.active_version_id;
|
||||||
const organizationId = templateQuery.data?.organization_id;
|
const organizationId = templateQuery.data?.organization_id;
|
||||||
@@ -96,7 +96,7 @@ const CreateWorkspacePage: FC = () => {
|
|||||||
const loadFormDataError =
|
const loadFormDataError =
|
||||||
templateQuery.error ?? permissionsQuery.error ?? richParametersQuery.error;
|
templateQuery.error ?? permissionsQuery.error ?? richParametersQuery.error;
|
||||||
|
|
||||||
const title = autoCreateWorkspaceMutation.isLoading
|
const title = autoCreateWorkspaceMutation.isPending
|
||||||
? "Creating workspace..."
|
? "Creating workspace..."
|
||||||
: "Create workspace";
|
: "Create workspace";
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ const CreateWorkspacePage: FC = () => {
|
|||||||
const autofillEnabled = experiments.includes("auto-fill-parameters");
|
const autofillEnabled = experiments.includes("auto-fill-parameters");
|
||||||
const userParametersQuery = useQuery({
|
const userParametersQuery = useQuery({
|
||||||
queryKey: ["userParameters"],
|
queryKey: ["userParameters"],
|
||||||
queryFn: () => API.getUserParameters(templateQuery.data!.id),
|
queryFn: () => API.getUserParameters(templateQuery.data?.id ?? ""),
|
||||||
enabled: autofillEnabled && templateQuery.isSuccess,
|
enabled: autofillEnabled && templateQuery.isSuccess,
|
||||||
});
|
});
|
||||||
const autofillParameters = getAutofillParameters(
|
const autofillParameters = getAutofillParameters(
|
||||||
@@ -203,7 +203,7 @@ const CreateWorkspacePage: FC = () => {
|
|||||||
autoCreateWorkspaceMutation.error
|
autoCreateWorkspaceMutation.error
|
||||||
}
|
}
|
||||||
resetMutation={createWorkspaceMutation.reset}
|
resetMutation={createWorkspaceMutation.reset}
|
||||||
template={templateQuery.data!}
|
template={templateQuery.data as Template}
|
||||||
versionId={realizedVersionId}
|
versionId={realizedVersionId}
|
||||||
externalAuth={externalAuth ?? []}
|
externalAuth={externalAuth ?? []}
|
||||||
externalAuthPollingState={externalAuthPollingState}
|
externalAuthPollingState={externalAuthPollingState}
|
||||||
@@ -212,7 +212,7 @@ const CreateWorkspacePage: FC = () => {
|
|||||||
permissions={permissionsQuery.data as CreateWorkspacePermissions}
|
permissions={permissionsQuery.data as CreateWorkspacePermissions}
|
||||||
parameters={realizedParameters as TemplateVersionParameter[]}
|
parameters={realizedParameters as TemplateVersionParameter[]}
|
||||||
presets={templateVersionPresetsQuery.data ?? []}
|
presets={templateVersionPresetsQuery.data ?? []}
|
||||||
creatingWorkspace={createWorkspaceMutation.isLoading}
|
creatingWorkspace={createWorkspaceMutation.isPending}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
navigate(-1);
|
navigate(-1);
|
||||||
}}
|
}}
|
||||||
@@ -245,15 +245,11 @@ const useExternalAuth = (versionId: string | undefined) => {
|
|||||||
setExternalAuthPollingState("polling");
|
setExternalAuthPollingState("polling");
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const { data: externalAuth, isLoading: isLoadingExternalAuth } = useQuery(
|
const { data: externalAuth, isPending: isLoadingExternalAuth } = useQuery({
|
||||||
versionId
|
...templateVersionExternalAuth(versionId ?? ""),
|
||||||
? {
|
enabled: !!versionId,
|
||||||
...templateVersionExternalAuth(versionId),
|
refetchInterval: externalAuthPollingState === "polling" ? 1000 : false,
|
||||||
refetchInterval:
|
});
|
||||||
externalAuthPollingState === "polling" ? 1000 : false,
|
|
||||||
}
|
|
||||||
: { enabled: false },
|
|
||||||
);
|
|
||||||
|
|
||||||
const allSignedIn = externalAuth?.every((it) => it.authenticated);
|
const allSignedIn = externalAuth?.every((it) => it.authenticated);
|
||||||
|
|
||||||
|
|||||||
@@ -73,18 +73,16 @@ const CreateWorkspacePageExperimental: FC = () => {
|
|||||||
const templateQuery = useQuery(
|
const templateQuery = useQuery(
|
||||||
templateByName(organizationName, templateName),
|
templateByName(organizationName, templateName),
|
||||||
);
|
);
|
||||||
const templateVersionPresetsQuery = useQuery(
|
const templateVersionPresetsQuery = useQuery({
|
||||||
templateQuery.data
|
...templateVersionPresets(templateQuery.data?.active_version_id ?? ""),
|
||||||
? templateVersionPresets(templateQuery.data.active_version_id)
|
enabled: !!templateQuery.data,
|
||||||
: { enabled: false },
|
});
|
||||||
);
|
const permissionsQuery = useQuery({
|
||||||
const permissionsQuery = useQuery(
|
...checkAuthorization({
|
||||||
templateQuery.data
|
checks: createWorkspaceChecks(templateQuery.data?.organization_id ?? ""),
|
||||||
? checkAuthorization({
|
}),
|
||||||
checks: createWorkspaceChecks(templateQuery.data.organization_id),
|
enabled: !!templateQuery.data,
|
||||||
})
|
});
|
||||||
: { enabled: false },
|
|
||||||
);
|
|
||||||
const realizedVersionId =
|
const realizedVersionId =
|
||||||
customVersionId ?? templateQuery.data?.active_version_id;
|
customVersionId ?? templateQuery.data?.active_version_id;
|
||||||
|
|
||||||
@@ -192,7 +190,7 @@ const CreateWorkspacePageExperimental: FC = () => {
|
|||||||
permissionsQuery.isLoading;
|
permissionsQuery.isLoading;
|
||||||
const loadFormDataError = templateQuery.error ?? permissionsQuery.error;
|
const loadFormDataError = templateQuery.error ?? permissionsQuery.error;
|
||||||
|
|
||||||
const title = autoCreateWorkspaceMutation.isLoading
|
const title = autoCreateWorkspaceMutation.isPending
|
||||||
? "Creating workspace..."
|
? "Creating workspace..."
|
||||||
: "Create workspace";
|
: "Create workspace";
|
||||||
|
|
||||||
@@ -308,7 +306,7 @@ const CreateWorkspacePageExperimental: FC = () => {
|
|||||||
permissions={permissionsQuery.data as CreateWorkspacePermissions}
|
permissions={permissionsQuery.data as CreateWorkspacePermissions}
|
||||||
parameters={sortedParams}
|
parameters={sortedParams}
|
||||||
presets={templateVersionPresetsQuery.data ?? []}
|
presets={templateVersionPresetsQuery.data ?? []}
|
||||||
creatingWorkspace={createWorkspaceMutation.isLoading}
|
creatingWorkspace={createWorkspaceMutation.isPending}
|
||||||
sendMessage={sendMessage}
|
sendMessage={sendMessage}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
navigate(-1);
|
navigate(-1);
|
||||||
@@ -344,15 +342,11 @@ const useExternalAuth = (versionId: string | undefined) => {
|
|||||||
setExternalAuthPollingState("polling");
|
setExternalAuthPollingState("polling");
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const { data: externalAuth, isLoading: isLoadingExternalAuth } = useQuery(
|
const { data: externalAuth, isLoading: isLoadingExternalAuth } = useQuery({
|
||||||
versionId
|
...templateVersionExternalAuth(versionId ?? ""),
|
||||||
? {
|
enabled: !!versionId,
|
||||||
...templateVersionExternalAuth(versionId),
|
refetchInterval: externalAuthPollingState === "polling" ? 1000 : false,
|
||||||
refetchInterval:
|
});
|
||||||
externalAuthPollingState === "polling" ? 1000 : false,
|
|
||||||
}
|
|
||||||
: { enabled: false },
|
|
||||||
);
|
|
||||||
|
|
||||||
const allSignedIn = externalAuth?.every((it) => it.authenticated);
|
const allSignedIn = externalAuth?.every((it) => it.authenticated);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ const AppearanceSettingsPage: FC = () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await updateAppearanceMutation.mutateAsync(newAppearance);
|
await updateAppearanceMutation.mutateAsync(newAppearance);
|
||||||
await queryClient.invalidateQueries(appearanceConfigKey);
|
await queryClient.invalidateQueries({ queryKey: appearanceConfigKey });
|
||||||
displaySuccess("Successfully updated appearance settings!");
|
displaySuccess("Successfully updated appearance settings!");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
displayError(
|
displayError(
|
||||||
|
|||||||
@@ -36,9 +36,10 @@ const IdpOrgSyncPage: FC = () => {
|
|||||||
setField(settingsQuery.data.field);
|
setField(settingsQuery.data.field);
|
||||||
}, [settingsQuery.data]);
|
}, [settingsQuery.data]);
|
||||||
|
|
||||||
const fieldValuesQuery = useQuery(
|
const fieldValuesQuery = useQuery({
|
||||||
field ? deploymentIdpSyncFieldValues(field) : { enabled: false },
|
...deploymentIdpSyncFieldValues(field),
|
||||||
);
|
enabled: !!field,
|
||||||
|
});
|
||||||
|
|
||||||
const patchOrganizationSyncSettingsMutation = useMutation(
|
const patchOrganizationSyncSettingsMutation = useMutation(
|
||||||
patchOrganizationSyncSettings(queryClient),
|
patchOrganizationSyncSettings(queryClient),
|
||||||
|
|||||||
@@ -12,9 +12,10 @@ const AddNewLicensePage: FC = () => {
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
mutate: saveLicenseKeyApi,
|
mutate: saveLicenseKeyApi,
|
||||||
isLoading: isCreating,
|
isPending: isCreating,
|
||||||
error: savingLicenseError,
|
error: savingLicenseError,
|
||||||
} = useMutation(API.createLicense, {
|
} = useMutation({
|
||||||
|
mutationFn: API.createLicense,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
displaySuccess("You have successfully added a license");
|
displaySuccess("You have successfully added a license");
|
||||||
navigate("/deployment/licenses?success=true");
|
navigate("/deployment/licenses?success=true");
|
||||||
|
|||||||
@@ -37,11 +37,12 @@ const LicensesSettingsPage: FC = () => {
|
|||||||
}
|
}
|
||||||
}, [entitlementsQuery.error]);
|
}, [entitlementsQuery.error]);
|
||||||
|
|
||||||
const { mutate: removeLicenseApi, isLoading: isRemovingLicense } =
|
const { mutate: removeLicenseApi, isPending: isRemovingLicense } =
|
||||||
useMutation(API.removeLicense, {
|
useMutation({
|
||||||
|
mutationFn: API.removeLicense,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
displaySuccess("Successfully removed license");
|
displaySuccess("Successfully removed license");
|
||||||
void queryClient.invalidateQueries(["licenses"]);
|
void queryClient.invalidateQueries({ queryKey: ["licenses"] });
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
displayError("Failed to remove license");
|
displayError("Failed to remove license");
|
||||||
@@ -77,7 +78,7 @@ const LicensesSettingsPage: FC = () => {
|
|||||||
<LicensesSettingsPageView
|
<LicensesSettingsPageView
|
||||||
showConfetti={confettiOn}
|
showConfetti={confettiOn}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
isRefreshing={refreshEntitlementsMutation.isLoading}
|
isRefreshing={refreshEntitlementsMutation.isPending}
|
||||||
userLimitActual={entitlementsQuery.data?.features.user_limit.actual}
|
userLimitActual={entitlementsQuery.data?.features.user_limit.actual}
|
||||||
userLimitLimit={entitlementsQuery.data?.features.user_limit.limit}
|
userLimitLimit={entitlementsQuery.data?.features.user_limit.limit}
|
||||||
licenses={licenses}
|
licenses={licenses}
|
||||||
|
|||||||
@@ -7,13 +7,11 @@ import type { FC } from "react";
|
|||||||
import { useMutation } from "react-query";
|
import { useMutation } from "react-query";
|
||||||
|
|
||||||
export const Troubleshooting: FC = () => {
|
export const Troubleshooting: FC = () => {
|
||||||
const { mutate: sendTestNotificationApi, isLoading } = useMutation(
|
const { mutate: sendTestNotificationApi, isPending } = useMutation({
|
||||||
API.postTestNotification,
|
mutationFn: API.postTestNotification,
|
||||||
{
|
onSuccess: () => displaySuccess("Test notification sent"),
|
||||||
onSuccess: () => displaySuccess("Test notification sent"),
|
onError: () => displayError("Failed to send test notification"),
|
||||||
onError: () => displayError("Failed to send test notification"),
|
});
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
return (
|
return (
|
||||||
@@ -33,12 +31,12 @@ export const Troubleshooting: FC = () => {
|
|||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
disabled={isLoading}
|
disabled={isPending}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
sendTestNotificationApi();
|
sendTestNotificationApi();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Spinner loading={isLoading} />
|
<Spinner loading={isPending} />
|
||||||
Send notification
|
Send notification
|
||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ const CreateOAuth2AppPage: FC = () => {
|
|||||||
</Helmet>
|
</Helmet>
|
||||||
|
|
||||||
<CreateOAuth2AppPageView
|
<CreateOAuth2AppPageView
|
||||||
isUpdating={postAppMutation.isLoading}
|
isUpdating={postAppMutation.isPending}
|
||||||
error={postAppMutation.error}
|
error={postAppMutation.error}
|
||||||
createApp={async (req) => {
|
createApp={async (req) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -39,10 +39,10 @@ const EditOAuth2AppPage: FC = () => {
|
|||||||
isLoadingApp={appQuery.isLoading}
|
isLoadingApp={appQuery.isLoading}
|
||||||
isLoadingSecrets={secretsQuery.isLoading}
|
isLoadingSecrets={secretsQuery.isLoading}
|
||||||
mutatingResource={{
|
mutatingResource={{
|
||||||
updateApp: putAppMutation.isLoading,
|
updateApp: putAppMutation.isPending,
|
||||||
deleteApp: deleteAppMutation.isLoading,
|
deleteApp: deleteAppMutation.isPending,
|
||||||
createSecret: postSecretMutation.isLoading,
|
createSecret: postSecretMutation.isPending,
|
||||||
deleteSecret: deleteSecretMutation.isLoading,
|
deleteSecret: deleteSecretMutation.isPending,
|
||||||
}}
|
}}
|
||||||
fullNewSecret={fullNewSecret}
|
fullNewSecret={fullNewSecret}
|
||||||
ackFullNewSecret={() => setFullNewSecret(undefined)}
|
ackFullNewSecret={() => setFullNewSecret(undefined)}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ const CreateGroupPage: FC = () => {
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
error={createGroupMutation.error}
|
error={createGroupMutation.error}
|
||||||
isLoading={createGroupMutation.isLoading}
|
isLoading={createGroupMutation.isPending}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { Meta, StoryObj } from "@storybook/react";
|
import type { Meta, StoryObj } from "@storybook/react";
|
||||||
import { userEvent, within } from "@storybook/test";
|
import { spyOn, userEvent, within } from "@storybook/test";
|
||||||
|
import { API } from "api/api";
|
||||||
import { getGroupQueryKey, groupPermissionsKey } from "api/queries/groups";
|
import { getGroupQueryKey, groupPermissionsKey } from "api/queries/groups";
|
||||||
import { organizationMembersKey } from "api/queries/organizations";
|
import { organizationMembersKey } from "api/queries/organizations";
|
||||||
import { reactRouterParameters } from "storybook-addon-remix-react-router";
|
import { reactRouterParameters } from "storybook-addon-remix-react-router";
|
||||||
@@ -52,11 +53,9 @@ export const LoadingGroup: Story = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const GroupError: Story = {
|
export const GroupError: Story = {
|
||||||
parameters: {
|
beforeEach: () => {
|
||||||
queries: [
|
spyOn(API, "getGroup").mockRejectedValue(new Error("test group error"));
|
||||||
{ ...groupQuery(new Error("test group error")), isError: true },
|
spyOn(API, "checkAuthorization").mockResolvedValue({});
|
||||||
permissionsQuery({}),
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -89,16 +88,19 @@ export const EveryoneGroup: Story = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const MembersError: Story = {
|
export const MembersError: Story = {
|
||||||
parameters: {
|
beforeEach() {
|
||||||
queries: [
|
spyOn(API, "getGroup").mockResolvedValue(MockGroup);
|
||||||
groupQuery(MockGroup),
|
spyOn(API, "checkAuthorization").mockResolvedValue({
|
||||||
permissionsQuery({ canUpdateGroup: true }),
|
canUpdateGroup: true,
|
||||||
{ ...membersQuery(new Error("test members error")), isError: true },
|
});
|
||||||
],
|
spyOn(API, "getOrganizationPaginatedMembers").mockRejectedValue(
|
||||||
|
new Error("test members error"),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
play: async ({ canvasElement }) => {
|
play: async ({ canvasElement }) => {
|
||||||
const canvas = within(canvasElement);
|
const canvas = within(canvasElement);
|
||||||
await userEvent.click(canvas.getByRole("button", { name: "Open" }));
|
const combobox = await canvas.findByRole("combobox");
|
||||||
|
await userEvent.click(combobox);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -115,7 +117,8 @@ export const NoMembers: Story = {
|
|||||||
},
|
},
|
||||||
play: async ({ canvasElement }) => {
|
play: async ({ canvasElement }) => {
|
||||||
const canvas = within(canvasElement);
|
const canvas = within(canvasElement);
|
||||||
await userEvent.click(canvas.getByRole("button", { name: "Open" }));
|
const combobox = await canvas.findByRole("combobox");
|
||||||
|
await userEvent.click(combobox);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -67,9 +67,10 @@ const GroupPage: FC = () => {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const groupQuery = useQuery(group(organization, groupName));
|
const groupQuery = useQuery(group(organization, groupName));
|
||||||
const groupData = groupQuery.data;
|
const groupData = groupQuery.data;
|
||||||
const { data: permissions } = useQuery(
|
const { data: permissions } = useQuery({
|
||||||
groupData ? groupPermissions(groupData.id) : { enabled: false },
|
...groupPermissions(groupData?.id ?? ""),
|
||||||
);
|
enabled: !!groupData,
|
||||||
|
});
|
||||||
const addMemberMutation = useMutation(addMember(queryClient));
|
const addMemberMutation = useMutation(addMember(queryClient));
|
||||||
const removeMemberMutation = useMutation(removeMember(queryClient));
|
const removeMemberMutation = useMutation(removeMember(queryClient));
|
||||||
const deleteGroupMutation = useMutation(deleteGroup(queryClient));
|
const deleteGroupMutation = useMutation(deleteGroup(queryClient));
|
||||||
@@ -145,7 +146,7 @@ const GroupPage: FC = () => {
|
|||||||
<Stack spacing={1}>
|
<Stack spacing={1}>
|
||||||
{canUpdateGroup && groupData && !isEveryoneGroup(groupData) && (
|
{canUpdateGroup && groupData && !isEveryoneGroup(groupData) && (
|
||||||
<AddGroupMember
|
<AddGroupMember
|
||||||
isLoading={addMemberMutation.isLoading}
|
isLoading={addMemberMutation.isPending}
|
||||||
organizationId={groupData.organization_id}
|
organizationId={groupData.organization_id}
|
||||||
onSubmit={async (member, reset) => {
|
onSubmit={async (member, reset) => {
|
||||||
try {
|
try {
|
||||||
@@ -220,7 +221,7 @@ const GroupPage: FC = () => {
|
|||||||
{groupQuery.data && (
|
{groupQuery.data && (
|
||||||
<DeleteDialog
|
<DeleteDialog
|
||||||
isOpen={isDeletingGroup}
|
isOpen={isDeletingGroup}
|
||||||
confirmLoading={deleteGroupMutation.isLoading}
|
confirmLoading={deleteGroupMutation.isPending}
|
||||||
name={groupQuery.data.name}
|
name={groupQuery.data.name}
|
||||||
entity="group"
|
entity="group"
|
||||||
onConfirm={async () => {
|
onConfirm={async () => {
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ const GroupSettingsPage: FC = () => {
|
|||||||
group={groupQuery.data}
|
group={groupQuery.data}
|
||||||
formErrors={groupQuery.error}
|
formErrors={groupQuery.error}
|
||||||
isLoading={groupQuery.isLoading}
|
isLoading={groupQuery.isLoading}
|
||||||
isUpdating={patchGroupMutation.isLoading}
|
isUpdating={patchGroupMutation.isPending}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -25,14 +25,14 @@ import { GroupsPageView } from "./GroupsPageView";
|
|||||||
const GroupsPage: FC = () => {
|
const GroupsPage: FC = () => {
|
||||||
const { template_rbac: groupsEnabled } = useFeatureVisibility();
|
const { template_rbac: groupsEnabled } = useFeatureVisibility();
|
||||||
const { organization, showOrganizations } = useGroupsSettings();
|
const { organization, showOrganizations } = useGroupsSettings();
|
||||||
const groupsQuery = useQuery(
|
const groupsQuery = useQuery({
|
||||||
organization ? groupsByOrganization(organization.name) : { enabled: false },
|
...groupsByOrganization(organization?.name ?? ""),
|
||||||
);
|
enabled: !!organization,
|
||||||
const permissionsQuery = useQuery(
|
});
|
||||||
organization
|
const permissionsQuery = useQuery({
|
||||||
? organizationsPermissions([organization.id])
|
...organizationsPermissions([organization?.id ?? ""]),
|
||||||
: { enabled: false },
|
enabled: !!organization,
|
||||||
);
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (groupsQuery.error) {
|
if (groupsQuery.error) {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export const DismissWarningButton = (props: { healthcheck: HealthSection }) => {
|
|||||||
if (isDismissed) {
|
if (isDismissed) {
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
disabled={healthSettingsQuery.isLoading || enableMutation.isLoading}
|
disabled={healthSettingsQuery.isLoading || enableMutation.isPending}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
const updatedSettings = dismissed_healthchecks.filter(
|
const updatedSettings = dismissed_healthchecks.filter(
|
||||||
@@ -48,7 +48,7 @@ export const DismissWarningButton = (props: { healthcheck: HealthSection }) => {
|
|||||||
displaySuccess("Warnings enabled successfully!");
|
displaySuccess("Warnings enabled successfully!");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Spinner loading={enableMutation.isLoading}>
|
<Spinner loading={enableMutation.isPending}>
|
||||||
<NotificationsOffOutlined />
|
<NotificationsOffOutlined />
|
||||||
</Spinner>
|
</Spinner>
|
||||||
Enable warnings
|
Enable warnings
|
||||||
@@ -58,7 +58,7 @@ export const DismissWarningButton = (props: { healthcheck: HealthSection }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
disabled={healthSettingsQuery.isLoading || dismissMutation.isLoading}
|
disabled={healthSettingsQuery.isLoading || dismissMutation.isPending}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
const updatedSettings = [...dismissed_healthchecks, props.healthcheck];
|
const updatedSettings = [...dismissed_healthchecks, props.healthcheck];
|
||||||
@@ -68,7 +68,7 @@ export const DismissWarningButton = (props: { healthcheck: HealthSection }) => {
|
|||||||
displaySuccess("Warnings dismissed successfully!");
|
displaySuccess("Warnings dismissed successfully!");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Spinner loading={dismissMutation.isLoading}>
|
<Spinner loading={dismissMutation.isPending}>
|
||||||
<NotificationOutlined />
|
<NotificationOutlined />
|
||||||
</Spinner>
|
</Spinner>
|
||||||
Dismiss warnings
|
Dismiss warnings
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export const HealthLayout: FC = () => {
|
|||||||
...health(),
|
...health(),
|
||||||
refetchInterval: 30_000,
|
refetchInterval: 30_000,
|
||||||
});
|
});
|
||||||
const { mutate: forceRefresh, isLoading: isRefreshing } = useMutation(
|
const { mutate: forceRefresh, isPending: isRefreshing } = useMutation(
|
||||||
refreshHealth(queryClient),
|
refreshHealth(queryClient),
|
||||||
);
|
);
|
||||||
const sections = {
|
const sections = {
|
||||||
|
|||||||
@@ -84,8 +84,8 @@ const CreateEditRolePage: FC = () => {
|
|||||||
}
|
}
|
||||||
isLoading={
|
isLoading={
|
||||||
role
|
role
|
||||||
? updateOrganizationRoleMutation.isLoading
|
? updateOrganizationRoleMutation.isPending
|
||||||
: createOrganizationRoleMutation.isLoading
|
: createOrganizationRoleMutation.isPending
|
||||||
}
|
}
|
||||||
organizationName={organizationName}
|
organizationName={organizationName}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ const CustomRolesPage: FC = () => {
|
|||||||
<DeleteDialog
|
<DeleteDialog
|
||||||
key={roleToDelete?.name}
|
key={roleToDelete?.name}
|
||||||
isOpen={roleToDelete !== undefined}
|
isOpen={roleToDelete !== undefined}
|
||||||
confirmLoading={deleteRoleMutation.isLoading}
|
confirmLoading={deleteRoleMutation.isPending}
|
||||||
name={roleToDelete?.name ?? ""}
|
name={roleToDelete?.name ?? ""}
|
||||||
entity="role"
|
entity="role"
|
||||||
onCancel={() => setRoleToDelete(undefined)}
|
onCancel={() => setRoleToDelete(undefined)}
|
||||||
|
|||||||
@@ -70,11 +70,10 @@ const IdpSyncPage: FC = () => {
|
|||||||
const tab = searchParams.get("tab") || "groups";
|
const tab = searchParams.get("tab") || "groups";
|
||||||
const field = tab === "groups" ? groupField : roleField;
|
const field = tab === "groups" ? groupField : roleField;
|
||||||
|
|
||||||
const fieldValuesQuery = useQuery(
|
const fieldValuesQuery = useQuery({
|
||||||
field
|
...organizationIdpSyncClaimFieldValues(organizationName, field),
|
||||||
? organizationIdpSyncClaimFieldValues(organizationName, field)
|
enabled: !!field,
|
||||||
: { enabled: false },
|
});
|
||||||
);
|
|
||||||
|
|
||||||
if (!organization) {
|
if (!organization) {
|
||||||
return <EmptyState message="Organization not found" />;
|
return <EmptyState message="Organization not found" />;
|
||||||
|
|||||||
@@ -98,8 +98,8 @@ const OrganizationMembersPage: FC = () => {
|
|||||||
removeMemberMutation.error ??
|
removeMemberMutation.error ??
|
||||||
updateMemberRolesMutation.error
|
updateMemberRolesMutation.error
|
||||||
}
|
}
|
||||||
isAddingMember={addMemberMutation.isLoading}
|
isAddingMember={addMemberMutation.isPending}
|
||||||
isUpdatingMemberRoles={updateMemberRolesMutation.isLoading}
|
isUpdatingMemberRoles={updateMemberRolesMutation.isPending}
|
||||||
me={me}
|
me={me}
|
||||||
members={members}
|
members={members}
|
||||||
membersQuery={membersQuery}
|
membersQuery={membersQuery}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ interface OrganizationMembersPageViewProps {
|
|||||||
me: User;
|
me: User;
|
||||||
members: Array<OrganizationMemberTableEntry> | undefined;
|
members: Array<OrganizationMemberTableEntry> | undefined;
|
||||||
membersQuery: PaginationResultInfo & {
|
membersQuery: PaginationResultInfo & {
|
||||||
isPreviousData: boolean;
|
isPlaceholderData: boolean;
|
||||||
};
|
};
|
||||||
addMember: (user: User) => Promise<void>;
|
addMember: (user: User) => Promise<void>;
|
||||||
removeMember: (member: OrganizationMemberWithUserData) => void;
|
removeMember: (member: OrganizationMemberWithUserData) => void;
|
||||||
|
|||||||
+7
-7
@@ -27,12 +27,12 @@ export const CancelJobConfirmationDialog: FC<
|
|||||||
const cancelMutation = useMutation({
|
const cancelMutation = useMutation({
|
||||||
mutationFn: cancelProvisionerJob,
|
mutationFn: cancelProvisionerJob,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries(
|
queryClient.invalidateQueries({
|
||||||
provisionerJobsQueryKey(job.organization_id),
|
queryKey: provisionerJobsQueryKey(job.organization_id),
|
||||||
);
|
});
|
||||||
queryClient.invalidateQueries(
|
queryClient.invalidateQueries({
|
||||||
getProvisionerDaemonsKey(job.organization_id, job.tags),
|
queryKey: getProvisionerDaemonsKey(job.organization_id, job.tags),
|
||||||
);
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ export const CancelJobConfirmationDialog: FC<
|
|||||||
description={`Are you sure you want to cancel the provisioner job "${job.id}"? This operation will result in the associated workspaces not getting created.`}
|
description={`Are you sure you want to cancel the provisioner job "${job.id}"? This operation will result in the associated workspaces not getting created.`}
|
||||||
confirmText="Confirm"
|
confirmText="Confirm"
|
||||||
cancelText="Discard"
|
cancelText="Discard"
|
||||||
confirmLoading={cancelMutation.isLoading}
|
confirmLoading={cancelMutation.isPending}
|
||||||
onConfirm={async () => {
|
onConfirm={async () => {
|
||||||
try {
|
try {
|
||||||
await cancelMutation.mutateAsync(job);
|
await cancelMutation.mutateAsync(job);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ const RequestOTPPage: FC = () => {
|
|||||||
) : (
|
) : (
|
||||||
<RequestOTP
|
<RequestOTP
|
||||||
error={requestOTPMutation.error}
|
error={requestOTPMutation.error}
|
||||||
isRequesting={requestOTPMutation.isLoading}
|
isRequesting={requestOTPMutation.isPending}
|
||||||
onRequest={(email) => {
|
onRequest={(email) => {
|
||||||
requestOTPMutation.mutate({ email });
|
requestOTPMutation.mutate({ email });
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export const SetupPage: FC = () => {
|
|||||||
</Helmet>
|
</Helmet>
|
||||||
<SetupPageView
|
<SetupPageView
|
||||||
authMethods={authMethodsQuery.data}
|
authMethods={authMethodsQuery.data}
|
||||||
isLoading={isSigningIn || createFirstUserMutation.isLoading}
|
isLoading={isSigningIn || createFirstUserMutation.isPending}
|
||||||
error={createFirstUserMutation.error}
|
error={createFirstUserMutation.error}
|
||||||
onSubmit={async (firstUser) => {
|
onSubmit={async (firstUser) => {
|
||||||
await createFirstUserMutation.mutateAsync(firstUser);
|
await createFirstUserMutation.mutateAsync(firstUser);
|
||||||
|
|||||||
@@ -84,20 +84,23 @@ export const TemplateLayout: FC<PropsWithChildren> = ({
|
|||||||
queryKey: ["template", templateName],
|
queryKey: ["template", templateName],
|
||||||
queryFn: () => fetchTemplate(organizationName, templateName),
|
queryFn: () => fetchTemplate(organizationName, templateName),
|
||||||
});
|
});
|
||||||
const workspacePermissionsQuery = useQuery(
|
const workspacePermissionsQuery = useQuery({
|
||||||
data
|
...checkAuthorization({
|
||||||
? checkAuthorization({
|
checks: workspacePermissionChecks(
|
||||||
checks: workspacePermissionChecks(
|
data?.template.organization_id ?? "",
|
||||||
data.template.organization_id,
|
me.id,
|
||||||
me.id,
|
),
|
||||||
),
|
}),
|
||||||
})
|
enabled: !!data,
|
||||||
: { enabled: false },
|
});
|
||||||
);
|
|
||||||
|
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const paths = location.pathname.split("/");
|
const paths = location.pathname.split("/");
|
||||||
const activeTab = paths.at(-1) === templateName ? "summary" : paths.at(-1)!;
|
const templateNamePath = paths.at(-1);
|
||||||
|
const activeTab =
|
||||||
|
templateNamePath === templateName
|
||||||
|
? "summary"
|
||||||
|
: (templateNamePath as string);
|
||||||
// Auditors should also be able to view insights, but do not automatically
|
// Auditors should also be able to view insights, but do not automatically
|
||||||
// have permission to update templates. Need both checks.
|
// have permission to update templates. Need both checks.
|
||||||
const shouldShowInsights =
|
const shouldShowInsights =
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const TemplateVersionsPage = () => {
|
|||||||
const [latestActiveVersion, setLatestActiveVersion] = useState(
|
const [latestActiveVersion, setLatestActiveVersion] = useState(
|
||||||
template.active_version_id,
|
template.active_version_id,
|
||||||
);
|
);
|
||||||
const { mutate: promoteVersion, isLoading: isPromoting } = useMutation({
|
const { mutate: promoteVersion, isPending: isPromoting } = useMutation({
|
||||||
mutationFn: (templateVersionId: string) => {
|
mutationFn: (templateVersionId: string) => {
|
||||||
return API.updateActiveTemplateVersion(template.id, {
|
return API.updateActiveTemplateVersion(template.id, {
|
||||||
id: templateVersionId,
|
id: templateVersionId,
|
||||||
@@ -35,7 +35,7 @@ const TemplateVersionsPage = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { mutate: archiveVersion, isLoading: isArchiving } = useMutation({
|
const { mutate: archiveVersion, isPending: isArchiving } = useMutation({
|
||||||
mutationFn: (templateVersionId: string) => {
|
mutationFn: (templateVersionId: string) => {
|
||||||
return API.archiveTemplateVersion(templateVersionId);
|
return API.archiveTemplateVersion(templateVersionId);
|
||||||
},
|
},
|
||||||
|
|||||||
+23
-25
@@ -28,35 +28,33 @@ const TemplateSettingsPage: FC = () => {
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
mutate: updateTemplate,
|
mutate: updateTemplate,
|
||||||
isLoading: isSubmitting,
|
isPending: isSubmitting,
|
||||||
error: submitError,
|
error: submitError,
|
||||||
} = useMutation(
|
} = useMutation({
|
||||||
(data: UpdateTemplateMeta) => {
|
mutationFn: (data: UpdateTemplateMeta) => {
|
||||||
return API.updateTemplateMeta(template.id, data);
|
return API.updateTemplateMeta(template.id, data);
|
||||||
},
|
},
|
||||||
{
|
onSuccess: async (data) => {
|
||||||
onSuccess: async (data) => {
|
// This update has a chance to return a 304 which means nothing was updated.
|
||||||
// This update has a chance to return a 304 which means nothing was updated.
|
// In this case, the return payload will be empty and we should use the
|
||||||
// In this case, the return payload will be empty and we should use the
|
// original template data.
|
||||||
// original template data.
|
if (!data) {
|
||||||
if (!data) {
|
data = template;
|
||||||
data = template;
|
} else {
|
||||||
} else {
|
// Only invalid the query if data is returned, indicating at least one field was updated.
|
||||||
// Only invalid the query if data is returned, indicating at least one field was updated.
|
//
|
||||||
//
|
// we use data.name because an admin may have updated templateName to something new
|
||||||
// we use data.name because an admin may have updated templateName to something new
|
await queryClient.invalidateQueries({
|
||||||
await queryClient.invalidateQueries(
|
queryKey: templateByNameKey(template.organization_name, data.name),
|
||||||
templateByNameKey(template.organization_name, data.name),
|
});
|
||||||
);
|
}
|
||||||
}
|
displaySuccess("Template updated successfully");
|
||||||
displaySuccess("Template updated successfully");
|
navigate(getLink(linkToTemplate(data.organization_name, data.name)));
|
||||||
navigate(getLink(linkToTemplate(data.organization_name, data.name)));
|
|
||||||
},
|
|
||||||
onError: (error) => {
|
|
||||||
displayError(getErrorMessage(error, "Failed to update template"));
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
);
|
onError: (error) => {
|
||||||
|
displayError(getErrorMessage(error, "Failed to update template"));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
+4
-4
@@ -48,7 +48,7 @@ const TemplatePermissionsPage: FC = () => {
|
|||||||
});
|
});
|
||||||
reset();
|
reset();
|
||||||
}}
|
}}
|
||||||
isAddingUser={addUserMutation.isLoading}
|
isAddingUser={addUserMutation.isPending}
|
||||||
onUpdateUser={async (user, role) => {
|
onUpdateUser={async (user, role) => {
|
||||||
await updateUserMutation.mutateAsync({
|
await updateUserMutation.mutateAsync({
|
||||||
templateId: template.id,
|
templateId: template.id,
|
||||||
@@ -58,7 +58,7 @@ const TemplatePermissionsPage: FC = () => {
|
|||||||
displaySuccess("User role updated successfully!");
|
displaySuccess("User role updated successfully!");
|
||||||
}}
|
}}
|
||||||
updatingUserId={
|
updatingUserId={
|
||||||
updateUserMutation.isLoading
|
updateUserMutation.isPending
|
||||||
? updateUserMutation.variables?.userId
|
? updateUserMutation.variables?.userId
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
@@ -78,7 +78,7 @@ const TemplatePermissionsPage: FC = () => {
|
|||||||
});
|
});
|
||||||
reset();
|
reset();
|
||||||
}}
|
}}
|
||||||
isAddingGroup={addGroupMutation.isLoading}
|
isAddingGroup={addGroupMutation.isPending}
|
||||||
onUpdateGroup={async (group, role) => {
|
onUpdateGroup={async (group, role) => {
|
||||||
await updateGroupMutation.mutateAsync({
|
await updateGroupMutation.mutateAsync({
|
||||||
templateId: template.id,
|
templateId: template.id,
|
||||||
@@ -88,7 +88,7 @@ const TemplatePermissionsPage: FC = () => {
|
|||||||
displaySuccess("Group role updated successfully!");
|
displaySuccess("Group role updated successfully!");
|
||||||
}}
|
}}
|
||||||
updatingGroupId={
|
updatingGroupId={
|
||||||
updateGroupMutation.isLoading
|
updateGroupMutation.isPending
|
||||||
? updateGroupMutation.variables?.groupId
|
? updateGroupMutation.variables?.groupId
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -7,7 +7,7 @@ import type { Group, ReducedUser } from "api/typesGenerated";
|
|||||||
import { AvatarData } from "components/Avatar/AvatarData";
|
import { AvatarData } from "components/Avatar/AvatarData";
|
||||||
import { useDebouncedFunction } from "hooks/debounce";
|
import { useDebouncedFunction } from "hooks/debounce";
|
||||||
import { type ChangeEvent, type FC, useState } from "react";
|
import { type ChangeEvent, type FC, useState } from "react";
|
||||||
import { useQuery } from "react-query";
|
import { keepPreviousData, useQuery } from "react-query";
|
||||||
import { prepareQuery } from "utils/filters";
|
import { prepareQuery } from "utils/filters";
|
||||||
import { getGroupSubtitle } from "utils/groups";
|
import { getGroupSubtitle } from "utils/groups";
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ export const UserOrGroupAutocomplete: FC<UserOrGroupAutocompleteProps> = ({
|
|||||||
limit: 25,
|
limit: 25,
|
||||||
}),
|
}),
|
||||||
enabled: autoComplete.open,
|
enabled: autoComplete.open,
|
||||||
keepPreviousData: true,
|
placeholderData: keepPreviousData,
|
||||||
});
|
});
|
||||||
const options = aclAvailableQuery.data
|
const options = aclAvailableQuery.data
|
||||||
? [
|
? [
|
||||||
|
|||||||
@@ -25,22 +25,21 @@ const TemplateSchedulePage: FC = () => {
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
mutate: updateTemplate,
|
mutate: updateTemplate,
|
||||||
isLoading: isSubmitting,
|
isPending: isSubmitting,
|
||||||
error: submitError,
|
error: submitError,
|
||||||
} = useMutation(
|
} = useMutation({
|
||||||
(data: UpdateTemplateMeta) => API.updateTemplateMeta(template.id, data),
|
mutationFn: (data: UpdateTemplateMeta) =>
|
||||||
{
|
API.updateTemplateMeta(template.id, data),
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(
|
await queryClient.invalidateQueries({
|
||||||
templateByNameKey(organizationName, templateName),
|
queryKey: templateByNameKey(organizationName, templateName),
|
||||||
);
|
});
|
||||||
displaySuccess("Template updated successfully");
|
displaySuccess("Template updated successfully");
|
||||||
// clear browser storage of workspaces impending deletion
|
// clear browser storage of workspaces impending deletion
|
||||||
localStorage.removeItem("dismissedWorkspaceList"); // workspaces page
|
localStorage.removeItem("dismissedWorkspaceList"); // workspaces page
|
||||||
localStorage.removeItem("dismissedWorkspace"); // workspace page
|
localStorage.removeItem("dismissedWorkspace"); // workspace page
|
||||||
},
|
|
||||||
},
|
},
|
||||||
);
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ const queryClient = new QueryClient({
|
|||||||
defaultOptions: {
|
defaultOptions: {
|
||||||
queries: {
|
queries: {
|
||||||
retry: false,
|
retry: false,
|
||||||
cacheTime: 0,
|
gcTime: 0,
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
networkMode: "offlineFirst",
|
networkMode: "offlineFirst",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export const TemplateSettingsLayout: FC = () => {
|
|||||||
enabled: templateQuery.isSuccess,
|
enabled: templateQuery.isSuccess,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (templateQuery.isLoading || permissionsQuery.isLoading) {
|
if (!(templateQuery.data && permissionsQuery.data)) {
|
||||||
return <Loader />;
|
return <Loader />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-5
@@ -15,7 +15,12 @@ import { Loader } from "components/Loader/Loader";
|
|||||||
import { linkToTemplate, useLinks } from "modules/navigation";
|
import { linkToTemplate, useLinks } from "modules/navigation";
|
||||||
import { type FC, useCallback } from "react";
|
import { type FC, useCallback } from "react";
|
||||||
import { Helmet } from "react-helmet-async";
|
import { Helmet } from "react-helmet-async";
|
||||||
import { useMutation, useQuery, useQueryClient } from "react-query";
|
import {
|
||||||
|
keepPreviousData,
|
||||||
|
useMutation,
|
||||||
|
useQuery,
|
||||||
|
useQueryClient,
|
||||||
|
} from "react-query";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { pageTitle } from "utils/page";
|
import { pageTitle } from "utils/page";
|
||||||
import { useTemplateSettings } from "../TemplateSettingsLayout";
|
import { useTemplateSettings } from "../TemplateSettingsLayout";
|
||||||
@@ -36,25 +41,28 @@ const TemplateVariablesPage: FC = () => {
|
|||||||
data: version,
|
data: version,
|
||||||
error: versionError,
|
error: versionError,
|
||||||
isLoading: isVersionLoading,
|
isLoading: isVersionLoading,
|
||||||
} = useQuery({ ...templateVersion(versionId), keepPreviousData: true });
|
} = useQuery({
|
||||||
|
...templateVersion(versionId),
|
||||||
|
placeholderData: keepPreviousData,
|
||||||
|
});
|
||||||
const {
|
const {
|
||||||
data: variables,
|
data: variables,
|
||||||
error: variablesError,
|
error: variablesError,
|
||||||
isLoading: isVariablesLoading,
|
isLoading: isVariablesLoading,
|
||||||
} = useQuery({
|
} = useQuery({
|
||||||
...templateVersionVariables(versionId),
|
...templateVersionVariables(versionId),
|
||||||
keepPreviousData: true,
|
placeholderData: keepPreviousData,
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
mutateAsync: sendCreateAndBuildTemplateVersion,
|
mutateAsync: sendCreateAndBuildTemplateVersion,
|
||||||
error: buildError,
|
error: buildError,
|
||||||
isLoading: isBuilding,
|
isPending: isBuilding,
|
||||||
} = useMutation(createAndBuildTemplateVersion(organization));
|
} = useMutation(createAndBuildTemplateVersion(organization));
|
||||||
const {
|
const {
|
||||||
mutateAsync: sendUpdateActiveTemplateVersion,
|
mutateAsync: sendUpdateActiveTemplateVersion,
|
||||||
error: publishError,
|
error: publishError,
|
||||||
isLoading: isPublishing,
|
isPending: isPublishing,
|
||||||
} = useMutation(updateActiveTemplateVersion(template, queryClient));
|
} = useMutation(updateActiveTemplateVersion(template, queryClient));
|
||||||
|
|
||||||
const publishVersion = useCallback(
|
const publishVersion = useCallback(
|
||||||
|
|||||||
@@ -18,7 +18,12 @@ import { linkToTemplate, useLinks } from "modules/navigation";
|
|||||||
import { useWatchVersionLogs } from "modules/templates/useWatchVersionLogs";
|
import { useWatchVersionLogs } from "modules/templates/useWatchVersionLogs";
|
||||||
import { type FC, useEffect, useState } from "react";
|
import { type FC, useEffect, useState } from "react";
|
||||||
import { Helmet } from "react-helmet-async";
|
import { Helmet } from "react-helmet-async";
|
||||||
import { useMutation, useQuery, useQueryClient } from "react-query";
|
import {
|
||||||
|
keepPreviousData,
|
||||||
|
useMutation,
|
||||||
|
useQuery,
|
||||||
|
useQueryClient,
|
||||||
|
} from "react-query";
|
||||||
import { useNavigate, useParams, useSearchParams } from "react-router-dom";
|
import { useNavigate, useParams, useSearchParams } from "react-router-dom";
|
||||||
import { type FileTree, existsFile, traverse } from "utils/filetree";
|
import { type FileTree, existsFile, traverse } from "utils/filetree";
|
||||||
import { pageTitle } from "utils/page";
|
import { pageTitle } from "utils/page";
|
||||||
@@ -50,9 +55,9 @@ const TemplateVersionEditorPage: FC = () => {
|
|||||||
);
|
);
|
||||||
const activeTemplateVersionQuery = useQuery({
|
const activeTemplateVersionQuery = useQuery({
|
||||||
...templateVersionOptions,
|
...templateVersionOptions,
|
||||||
keepPreviousData: true,
|
placeholderData: keepPreviousData,
|
||||||
refetchInterval(data) {
|
refetchInterval({ state }) {
|
||||||
return data?.job.status === "pending" ? 1_000 : false;
|
return state.data?.job.status === "pending" ? 1_000 : false;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const { data: activeTemplateVersion } = activeTemplateVersionQuery;
|
const { data: activeTemplateVersion } = activeTemplateVersionQuery;
|
||||||
@@ -79,9 +84,9 @@ const TemplateVersionEditorPage: FC = () => {
|
|||||||
const publishVersionMutation = useMutation({
|
const publishVersionMutation = useMutation({
|
||||||
mutationFn: publishVersion,
|
mutationFn: publishVersion,
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(
|
await queryClient.invalidateQueries({
|
||||||
templateByNameKey(organizationName, templateName),
|
queryKey: templateByNameKey(organizationName, templateName),
|
||||||
);
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const [lastSuccessfulPublishedVersion, setLastSuccessfulPublishedVersion] =
|
const [lastSuccessfulPublishedVersion, setLastSuccessfulPublishedVersion] =
|
||||||
@@ -183,7 +188,7 @@ const TemplateVersionEditorPage: FC = () => {
|
|||||||
navigateToVersion(publishedVersion);
|
navigateToVersion(publishedVersion);
|
||||||
}}
|
}}
|
||||||
isAskingPublishParameters={isPublishingDialogOpen}
|
isAskingPublishParameters={isPublishingDialogOpen}
|
||||||
isPublishing={publishVersionMutation.isLoading}
|
isPublishing={publishVersionMutation.isPending}
|
||||||
publishingError={publishVersionMutation.error}
|
publishingError={publishVersionMutation.error}
|
||||||
publishedVersion={lastSuccessfulPublishedVersion}
|
publishedVersion={lastSuccessfulPublishedVersion}
|
||||||
onCreateWorkspace={() => {
|
onCreateWorkspace={() => {
|
||||||
@@ -199,8 +204,8 @@ const TemplateVersionEditorPage: FC = () => {
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
isBuilding={
|
isBuilding={
|
||||||
createTemplateVersionMutation.isLoading ||
|
createTemplateVersionMutation.isPending ||
|
||||||
uploadFileMutation.isLoading ||
|
uploadFileMutation.isPending ||
|
||||||
activeTemplateVersion.job.status === "running" ||
|
activeTemplateVersion.job.status === "running" ||
|
||||||
activeTemplateVersion.job.status === "pending"
|
activeTemplateVersion.job.status === "pending"
|
||||||
}
|
}
|
||||||
@@ -345,9 +350,9 @@ const publishVersion = async (options: {
|
|||||||
publishActions.push(API.patchTemplateVersion(version.id, data));
|
publishActions.push(API.patchTemplateVersion(version.id, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isActiveVersion) {
|
if (version.template_id && isActiveVersion) {
|
||||||
publishActions.push(
|
publishActions.push(
|
||||||
API.updateActiveTemplateVersion(version.template_id!, {
|
API.updateActiveTemplateVersion(version.template_id, {
|
||||||
id: version.id,
|
id: version.id,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ const AppearancePage: FC = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AppearanceForm
|
<AppearanceForm
|
||||||
isUpdating={updateAppearanceSettingsMutation.isLoading}
|
isUpdating={updateAppearanceSettingsMutation.isPending}
|
||||||
error={updateAppearanceSettingsMutation.error}
|
error={updateAppearanceSettingsMutation.error}
|
||||||
initialValues={{
|
initialValues={{
|
||||||
theme_preference: appearanceSettingsQuery.data.theme_preference,
|
theme_preference: appearanceSettingsQuery.data.theme_preference,
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ const ExternalAuthPage: FC = () => {
|
|||||||
do so on the oauth2 provider's side."
|
do so on the oauth2 provider's side."
|
||||||
label="Name of the application to unlink"
|
label="Name of the application to unlink"
|
||||||
isOpen={appToUnlink !== undefined}
|
isOpen={appToUnlink !== undefined}
|
||||||
confirmLoading={unlinkAppMutation.isLoading}
|
confirmLoading={unlinkAppMutation.isPending}
|
||||||
name={appToUnlink ?? ""}
|
name={appToUnlink ?? ""}
|
||||||
entity="application"
|
entity="application"
|
||||||
onCancel={() => setAppToUnlink(undefined)}
|
onCancel={() => setAppToUnlink(undefined)}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const OAuth2ProviderPage: FC = () => {
|
|||||||
info={`This will invalidate any tokens created by the OAuth2 application "${appToRevoke.name}".`}
|
info={`This will invalidate any tokens created by the OAuth2 application "${appToRevoke.name}".`}
|
||||||
label="Name of the application to revoke"
|
label="Name of the application to revoke"
|
||||||
isOpen
|
isOpen
|
||||||
confirmLoading={revokeAppMutation.isLoading}
|
confirmLoading={revokeAppMutation.isPending}
|
||||||
name={appToRevoke.name}
|
name={appToRevoke.name}
|
||||||
entity="application"
|
entity="application"
|
||||||
onCancel={() => setAppIdToRevoke(undefined)}
|
onCancel={() => setAppIdToRevoke(undefined)}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ const SSHKeysPage: FC = () => {
|
|||||||
type="delete"
|
type="delete"
|
||||||
hideCancel={false}
|
hideCancel={false}
|
||||||
open={isConfirmingRegeneration}
|
open={isConfirmingRegeneration}
|
||||||
confirmLoading={regenerateSSHKeyMutation.isLoading}
|
confirmLoading={regenerateSSHKeyMutation.isPending}
|
||||||
title={Language.regenerateDialogTitle}
|
title={Language.regenerateDialogTitle}
|
||||||
description={Language.regenerateDialogMessage}
|
description={Language.regenerateDialogMessage}
|
||||||
confirmText={Language.confirmLabel}
|
confirmText={Language.confirmLabel}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import {
|
|||||||
updateUserQuietHoursSchedule,
|
updateUserQuietHoursSchedule,
|
||||||
userQuietHoursSchedule,
|
userQuietHoursSchedule,
|
||||||
} from "api/queries/settings";
|
} from "api/queries/settings";
|
||||||
|
import type { UserQuietHoursScheduleResponse } from "api/typesGenerated";
|
||||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||||
import { Loader } from "components/Loader/Loader";
|
import { Loader } from "components/Loader/Loader";
|
||||||
@@ -25,7 +26,7 @@ const SchedulePage: FC = () => {
|
|||||||
const {
|
const {
|
||||||
mutate: onSubmit,
|
mutate: onSubmit,
|
||||||
error: submitError,
|
error: submitError,
|
||||||
isLoading: mutationLoading,
|
isPending: mutationLoading,
|
||||||
} = useMutation(updateUserQuietHoursSchedule(me.id, queryClient));
|
} = useMutation(updateUserQuietHoursSchedule(me.id, queryClient));
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
@@ -44,7 +45,7 @@ const SchedulePage: FC = () => {
|
|||||||
>
|
>
|
||||||
<ScheduleForm
|
<ScheduleForm
|
||||||
isLoading={mutationLoading}
|
isLoading={mutationLoading}
|
||||||
initialValues={quietHoursSchedule}
|
initialValues={quietHoursSchedule as UserQuietHoursScheduleResponse}
|
||||||
submitError={submitError}
|
submitError={submitError}
|
||||||
onSubmit={(values) => {
|
onSubmit={(values) => {
|
||||||
onSubmit(values, {
|
onSubmit(values, {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const SecurityPage: FC = () => {
|
|||||||
form: {
|
form: {
|
||||||
disabled: userLoginType.login_type !== "password",
|
disabled: userLoginType.login_type !== "password",
|
||||||
error: updatePasswordMutation.error,
|
error: updatePasswordMutation.error,
|
||||||
isLoading: updatePasswordMutation.isLoading,
|
isLoading: updatePasswordMutation.isPending,
|
||||||
onSubmit: async (data) => {
|
onSubmit: async (data) => {
|
||||||
await updatePasswordMutation.mutateAsync({
|
await updatePasswordMutation.mutateAsync({
|
||||||
userId: me.id,
|
userId: me.id,
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const defaultArgs: ComponentProps<typeof SecurityPageView> = {
|
|||||||
authMethods: MockAuthMethodsPasswordOnly,
|
authMethods: MockAuthMethodsPasswordOnly,
|
||||||
closeConfirmation: action("closeConfirmation"),
|
closeConfirmation: action("closeConfirmation"),
|
||||||
confirm: action("confirm"),
|
confirm: action("confirm"),
|
||||||
error: undefined,
|
error: null,
|
||||||
isConfirming: false,
|
isConfirming: false,
|
||||||
isUpdating: false,
|
isUpdating: false,
|
||||||
openConfirmation: action("openConfirmation"),
|
openConfirmation: action("openConfirmation"),
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ export const useSingleSignOnSection = () => {
|
|||||||
const [loginTypeConfirmation, setLoginTypeConfirmation] =
|
const [loginTypeConfirmation, setLoginTypeConfirmation] =
|
||||||
useState<LoginTypeConfirmation>({ open: false, selectedType: undefined });
|
useState<LoginTypeConfirmation>({ open: false, selectedType: undefined });
|
||||||
|
|
||||||
const mutation = useMutation(API.convertToOAUTH, {
|
const mutation = useMutation({
|
||||||
|
mutationFn: API.convertToOAUTH,
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
const loginTypeMsg =
|
const loginTypeMsg =
|
||||||
data.to_type === "github" ? "Github" : "OpenID Connect";
|
data.to_type === "github" ? "Github" : "OpenID Connect";
|
||||||
@@ -93,7 +94,7 @@ export const useSingleSignOnSection = () => {
|
|||||||
confirm,
|
confirm,
|
||||||
// We still want to show it loading when it is success so the modal does not
|
// We still want to show it loading when it is success so the modal does not
|
||||||
// change until the redirect
|
// change until the redirect
|
||||||
isUpdating: mutation.isLoading || mutation.isSuccess,
|
isUpdating: mutation.isPending || mutation.isSuccess,
|
||||||
isConfirming: loginTypeConfirmation.open,
|
isConfirming: loginTypeConfirmation.open,
|
||||||
error: mutation.error,
|
error: mutation.error,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const queryClient = new QueryClient({
|
|||||||
defaultOptions: {
|
defaultOptions: {
|
||||||
queries: {
|
queries: {
|
||||||
retry: false,
|
retry: false,
|
||||||
cacheTime: 0,
|
gcTime: 0,
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export const ConfirmDeleteDialog: FC<ConfirmDeleteDialogProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const tokenName = token?.token_name;
|
const tokenName = token?.token_name;
|
||||||
|
|
||||||
const { mutate: deleteToken, isLoading: isDeleting } =
|
const { mutate: deleteToken, isPending: isDeleting } =
|
||||||
useDeleteToken(queryKey);
|
useDeleteToken(queryKey);
|
||||||
|
|
||||||
const onDeleteSuccess = () => {
|
const onDeleteSuccess = () => {
|
||||||
|
|||||||
@@ -29,7 +29,9 @@ export const useDeleteToken = (queryKey: QueryKey) => {
|
|||||||
mutationFn: API.deleteToken,
|
mutationFn: API.deleteToken,
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
// Invalidate and refetch
|
// Invalidate and refetch
|
||||||
void queryClient.invalidateQueries(queryKey);
|
void queryClient.invalidateQueries({
|
||||||
|
queryKey,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ const UsersPage: FC<UserPageProps> = ({ defaultNewPassword }) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
isUpdatingUserRoles={updateRolesMutation.isLoading}
|
isUpdatingUserRoles={updateRolesMutation.isPending}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
canEditUsers={canEditUsers}
|
canEditUsers={canEditUsers}
|
||||||
canViewActivity={entitlements.features.audit_log.enabled}
|
canViewActivity={entitlements.features.audit_log.enabled}
|
||||||
@@ -161,7 +161,7 @@ const UsersPage: FC<UserPageProps> = ({ defaultNewPassword }) => {
|
|||||||
<DeleteDialog
|
<DeleteDialog
|
||||||
key={userToDelete?.username}
|
key={userToDelete?.username}
|
||||||
isOpen={userToDelete !== undefined}
|
isOpen={userToDelete !== undefined}
|
||||||
confirmLoading={deleteUserMutation.isLoading}
|
confirmLoading={deleteUserMutation.isPending}
|
||||||
name={userToDelete?.username ?? ""}
|
name={userToDelete?.username ?? ""}
|
||||||
entity="user"
|
entity="user"
|
||||||
onCancel={() => setUserToDelete(undefined)}
|
onCancel={() => setUserToDelete(undefined)}
|
||||||
@@ -183,7 +183,7 @@ const UsersPage: FC<UserPageProps> = ({ defaultNewPassword }) => {
|
|||||||
type="delete"
|
type="delete"
|
||||||
hideCancel={false}
|
hideCancel={false}
|
||||||
open={userToSuspend !== undefined}
|
open={userToSuspend !== undefined}
|
||||||
confirmLoading={suspendUserMutation.isLoading}
|
confirmLoading={suspendUserMutation.isPending}
|
||||||
title="Suspend user"
|
title="Suspend user"
|
||||||
confirmText="Suspend"
|
confirmText="Suspend"
|
||||||
onClose={() => setUserToSuspend(undefined)}
|
onClose={() => setUserToSuspend(undefined)}
|
||||||
@@ -211,7 +211,7 @@ const UsersPage: FC<UserPageProps> = ({ defaultNewPassword }) => {
|
|||||||
type="success"
|
type="success"
|
||||||
hideCancel={false}
|
hideCancel={false}
|
||||||
open={userToActivate !== undefined}
|
open={userToActivate !== undefined}
|
||||||
confirmLoading={activateUserMutation.isLoading}
|
confirmLoading={activateUserMutation.isPending}
|
||||||
title="Activate user"
|
title="Activate user"
|
||||||
confirmText="Activate"
|
confirmText="Activate"
|
||||||
onClose={() => setUserToActivate(undefined)}
|
onClose={() => setUserToActivate(undefined)}
|
||||||
@@ -238,7 +238,7 @@ const UsersPage: FC<UserPageProps> = ({ defaultNewPassword }) => {
|
|||||||
<ResetPasswordDialog
|
<ResetPasswordDialog
|
||||||
key={confirmResetPassword?.user.username}
|
key={confirmResetPassword?.user.username}
|
||||||
open={confirmResetPassword !== undefined}
|
open={confirmResetPassword !== undefined}
|
||||||
loading={updatePasswordMutation.isLoading}
|
loading={updatePasswordMutation.isPending}
|
||||||
user={confirmResetPassword?.user}
|
user={confirmResetPassword?.user}
|
||||||
newPassword={confirmResetPassword?.newPassword}
|
newPassword={confirmResetPassword?.newPassword}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import dayjs from "dayjs";
|
|||||||
import { useWorkspaceBuildLogs } from "hooks/useWorkspaceBuildLogs";
|
import { useWorkspaceBuildLogs } from "hooks/useWorkspaceBuildLogs";
|
||||||
import type { FC } from "react";
|
import type { FC } from "react";
|
||||||
import { Helmet } from "react-helmet-async";
|
import { Helmet } from "react-helmet-async";
|
||||||
import { useQuery } from "react-query";
|
import { keepPreviousData, useQuery } from "react-query";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { pageTitle } from "utils/page";
|
import { pageTitle } from "utils/page";
|
||||||
import { WorkspaceBuildPageView } from "./WorkspaceBuildPageView";
|
import { WorkspaceBuildPageView } from "./WorkspaceBuildPageView";
|
||||||
@@ -20,7 +20,7 @@ const WorkspaceBuildPage: FC = () => {
|
|||||||
const username = params.username.replace("@", "");
|
const username = params.username.replace("@", "");
|
||||||
const wsBuildQuery = useQuery({
|
const wsBuildQuery = useQuery({
|
||||||
...workspaceBuildByNumber(username, workspaceName, buildNumber),
|
...workspaceBuildByNumber(username, workspaceName, buildNumber),
|
||||||
keepPreviousData: true,
|
placeholderData: keepPreviousData,
|
||||||
});
|
});
|
||||||
const build = wsBuildQuery.data;
|
const build = wsBuildQuery.data;
|
||||||
const buildsQuery = useQuery({
|
const buildsQuery = useQuery({
|
||||||
|
|||||||
@@ -36,11 +36,10 @@ const WorkspacePage: FC = () => {
|
|||||||
const workspace = workspaceQuery.data;
|
const workspace = workspaceQuery.data;
|
||||||
|
|
||||||
// Template
|
// Template
|
||||||
const templateQuery = useQuery(
|
const templateQuery = useQuery({
|
||||||
workspace
|
...templateQueryOptions(workspace?.template_id ?? ""),
|
||||||
? templateQueryOptions(workspace.template_id)
|
enabled: !!workspace,
|
||||||
: { enabled: false },
|
});
|
||||||
);
|
|
||||||
const template = templateQuery.data;
|
const template = templateQuery.data;
|
||||||
|
|
||||||
// Permissions
|
// Permissions
|
||||||
@@ -67,9 +66,9 @@ const WorkspacePage: FC = () => {
|
|||||||
newWorkspaceData.latest_build.status !== workspace.latest_build.status;
|
newWorkspaceData.latest_build.status !== workspace.latest_build.status;
|
||||||
|
|
||||||
if (hasNewBuild || lastBuildHasChanged) {
|
if (hasNewBuild || lastBuildHasChanged) {
|
||||||
await queryClient.invalidateQueries(
|
await queryClient.invalidateQueries({
|
||||||
workspaceBuildsKey(newWorkspaceData.id),
|
queryKey: workspaceBuildsKey(newWorkspaceData.id),
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export const WorkspaceReadyPage: FC<WorkspaceReadyPageProps> = ({
|
|||||||
open: boolean;
|
open: boolean;
|
||||||
buildParameters?: TypesGen.WorkspaceBuildParameter[];
|
buildParameters?: TypesGen.WorkspaceBuildParameter[];
|
||||||
}>({ open: false });
|
}>({ open: false });
|
||||||
const { mutate: mutateRestartWorkspace, isLoading: isRestarting } =
|
const { mutate: mutateRestartWorkspace, isPending: isRestarting } =
|
||||||
useMutation({
|
useMutation({
|
||||||
mutationFn: API.restartWorkspace,
|
mutationFn: API.restartWorkspace,
|
||||||
});
|
});
|
||||||
@@ -133,7 +133,8 @@ export const WorkspaceReadyPage: FC<WorkspaceReadyPageProps> = ({
|
|||||||
// timings. To refetch the timings, I found the best way was to compare the
|
// timings. To refetch the timings, I found the best way was to compare the
|
||||||
// expected amount of script timings that run on start, with the current
|
// expected amount of script timings that run on start, with the current
|
||||||
// amount of script timings returned in the response.
|
// amount of script timings returned in the response.
|
||||||
refetchInterval: (data) => {
|
refetchInterval: ({ state }) => {
|
||||||
|
const { data } = state;
|
||||||
const expectedScriptTimingsCount = workspace.latest_build.resources
|
const expectedScriptTimingsCount = workspace.latest_build.resources
|
||||||
.flatMap((r) => r.agents)
|
.flatMap((r) => r.agents)
|
||||||
.flatMap((a) => a?.scripts ?? [])
|
.flatMap((a) => a?.scripts ?? [])
|
||||||
|
|||||||
+27
-32
@@ -13,41 +13,36 @@ const WorkspaceParametersExperimentRouter: FC = () => {
|
|||||||
const workspace = useWorkspaceSettings();
|
const workspace = useWorkspaceSettings();
|
||||||
const dynamicParametersEnabled = experiments.includes("dynamic-parameters");
|
const dynamicParametersEnabled = experiments.includes("dynamic-parameters");
|
||||||
|
|
||||||
const optOutQuery = useQuery(
|
const optOutQuery = useQuery({
|
||||||
dynamicParametersEnabled
|
enabled: dynamicParametersEnabled,
|
||||||
? {
|
queryKey: [
|
||||||
queryKey: [
|
"workspace",
|
||||||
"workspace",
|
workspace.id,
|
||||||
workspace.id,
|
"template_id",
|
||||||
"template_id",
|
workspace.template_id,
|
||||||
workspace.template_id,
|
"optOut",
|
||||||
"optOut",
|
],
|
||||||
],
|
queryFn: () => {
|
||||||
queryFn: () => {
|
const templateId = workspace.template_id;
|
||||||
const templateId = workspace.template_id;
|
const workspaceId = workspace.id;
|
||||||
const workspaceId = workspace.id;
|
const localStorageKey = optOutKey(templateId);
|
||||||
const localStorageKey = optOutKey(templateId);
|
const storedOptOutString = localStorage.getItem(localStorageKey);
|
||||||
const storedOptOutString = localStorage.getItem(localStorageKey);
|
|
||||||
|
|
||||||
let optOutResult: boolean;
|
let optOutResult: boolean;
|
||||||
|
|
||||||
if (storedOptOutString !== null) {
|
if (storedOptOutString !== null) {
|
||||||
optOutResult = storedOptOutString === "true";
|
optOutResult = storedOptOutString === "true";
|
||||||
} else {
|
} else {
|
||||||
optOutResult = Boolean(
|
optOutResult = Boolean(workspace.template_use_classic_parameter_flow);
|
||||||
workspace.template_use_classic_parameter_flow,
|
}
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
templateId,
|
templateId,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
optedOut: optOutResult,
|
optedOut: optOutResult,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
}
|
});
|
||||||
: { enabled: false },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (dynamicParametersEnabled) {
|
if (dynamicParametersEnabled) {
|
||||||
if (optOutQuery.isLoading) {
|
if (optOutQuery.isLoading) {
|
||||||
|
|||||||
+1
-1
@@ -63,7 +63,7 @@ const WorkspaceParametersPage: FC = () => {
|
|||||||
canChangeVersions={canChangeVersions}
|
canChangeVersions={canChangeVersions}
|
||||||
data={parameters.data}
|
data={parameters.data}
|
||||||
submitError={updateParameters.error}
|
submitError={updateParameters.error}
|
||||||
isSubmitting={updateParameters.isLoading}
|
isSubmitting={updateParameters.isPending}
|
||||||
onSubmit={(values) => {
|
onSubmit={(values) => {
|
||||||
if (!parameters.data) {
|
if (!parameters.data) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
+1
-1
@@ -222,7 +222,7 @@ const WorkspaceParametersPageExperimental: FC = () => {
|
|||||||
canChangeVersions={canChangeVersions}
|
canChangeVersions={canChangeVersions}
|
||||||
parameters={sortedParams}
|
parameters={sortedParams}
|
||||||
diagnostics={latestResponse.diagnostics}
|
diagnostics={latestResponse.diagnostics}
|
||||||
isSubmitting={updateParameters.isLoading}
|
isSubmitting={updateParameters.isPending}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
onCancel={() =>
|
onCancel={() =>
|
||||||
navigate(`/@${workspace.owner_name}/${workspace.name}`)
|
navigate(`/@${workspace.owner_name}/${workspace.name}`)
|
||||||
|
|||||||
+4
-4
@@ -55,12 +55,12 @@ const WorkspaceSchedulePage: FC = () => {
|
|||||||
const submitScheduleMutation = useMutation({
|
const submitScheduleMutation = useMutation({
|
||||||
mutationFn: submitSchedule,
|
mutationFn: submitSchedule,
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(
|
await queryClient.invalidateQueries({
|
||||||
workspaceByOwnerAndNameKey(
|
queryKey: workspaceByOwnerAndNameKey(
|
||||||
params.username.replace(/^@/, ""),
|
params.username.replace(/^@/, ""),
|
||||||
params.workspace,
|
params.workspace,
|
||||||
),
|
),
|
||||||
);
|
});
|
||||||
displaySuccess("Workspace schedule updated");
|
displaySuccess("Workspace schedule updated");
|
||||||
},
|
},
|
||||||
onError: () => displayError("Failed to update workspace schedule"),
|
onError: () => displayError("Failed to update workspace schedule"),
|
||||||
@@ -102,7 +102,7 @@ const WorkspaceSchedulePage: FC = () => {
|
|||||||
...getAutostart(workspace),
|
...getAutostart(workspace),
|
||||||
...getAutostop(workspace),
|
...getAutostop(workspace),
|
||||||
}}
|
}}
|
||||||
isLoading={submitScheduleMutation.isLoading}
|
isLoading={submitScheduleMutation.isPending}
|
||||||
defaultTTL={dayjs.duration(template.default_ttl_ms, "ms").asHours()}
|
defaultTTL={dayjs.duration(template.default_ttl_ms, "ms").asHours()}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
navigate(`/@${username}/${workspaceName}`);
|
navigate(`/@${username}/${workspaceName}`);
|
||||||
|
|||||||
@@ -53,14 +53,16 @@ export const WorkspaceSettingsLayout: FC = () => {
|
|||||||
{isError ? (
|
{isError ? (
|
||||||
<ErrorAlert error={error} />
|
<ErrorAlert error={error} />
|
||||||
) : (
|
) : (
|
||||||
<WorkspaceSettings.Provider value={workspace}>
|
workspace && (
|
||||||
<Sidebar workspace={workspace} username={username} />
|
<WorkspaceSettings.Provider value={workspace}>
|
||||||
<Suspense fallback={<Loader />}>
|
<Sidebar workspace={workspace} username={username} />
|
||||||
<main css={{ width: "100%" }}>
|
<Suspense fallback={<Loader />}>
|
||||||
<Outlet />
|
<main css={{ width: "100%" }}>
|
||||||
</main>
|
<Outlet />
|
||||||
</Suspense>
|
</main>
|
||||||
</WorkspaceSettings.Provider>
|
</Suspense>
|
||||||
|
</WorkspaceSettings.Provider>
|
||||||
|
)
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
</Margins>
|
</Margins>
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ export const WorkspacesButton: FC<WorkspacesButtonProps> = ({
|
|||||||
paddingBottom: "8px",
|
paddingBottom: "8px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{templatesFetchStatus === "loading" ? (
|
{templatesFetchStatus === "pending" ? (
|
||||||
<Loader size="sm" />
|
<Loader size="sm" />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -77,8 +77,8 @@ const WorkspacesPage: FC = () => {
|
|||||||
});
|
});
|
||||||
const { data, error, refetch } = useQuery({
|
const { data, error, refetch } = useQuery({
|
||||||
...workspacesQueryOptions,
|
...workspacesQueryOptions,
|
||||||
refetchInterval: (_, query) => {
|
refetchInterval: ({ state }) => {
|
||||||
return query.state.error ? false : 5_000;
|
return state.error ? false : 5_000;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -489,9 +489,9 @@ const WorkspaceActionsCell: FC<WorkspaceActionsCellProps> = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const isRetrying =
|
const isRetrying =
|
||||||
startWorkspaceMutation.isLoading ||
|
startWorkspaceMutation.isPending ||
|
||||||
stopWorkspaceMutation.isLoading ||
|
stopWorkspaceMutation.isPending ||
|
||||||
deleteWorkspaceMutation.isLoading;
|
deleteWorkspaceMutation.isPending;
|
||||||
|
|
||||||
const retry = () => {
|
const retry = () => {
|
||||||
switch (workspace.latest_build.transition) {
|
switch (workspace.latest_build.transition) {
|
||||||
@@ -525,7 +525,7 @@ const WorkspaceActionsCell: FC<WorkspaceActionsCellProps> = ({
|
|||||||
{abilities.actions.includes("start") && (
|
{abilities.actions.includes("start") && (
|
||||||
<PrimaryAction
|
<PrimaryAction
|
||||||
onClick={() => startWorkspaceMutation.mutate({})}
|
onClick={() => startWorkspaceMutation.mutate({})}
|
||||||
isLoading={startWorkspaceMutation.isLoading}
|
isLoading={startWorkspaceMutation.isPending}
|
||||||
label="Start workspace"
|
label="Start workspace"
|
||||||
>
|
>
|
||||||
<PlayIcon />
|
<PlayIcon />
|
||||||
@@ -548,7 +548,7 @@ const WorkspaceActionsCell: FC<WorkspaceActionsCellProps> = ({
|
|||||||
{abilities.canCancel && (
|
{abilities.canCancel && (
|
||||||
<PrimaryAction
|
<PrimaryAction
|
||||||
onClick={cancelBuildMutation.mutate}
|
onClick={cancelBuildMutation.mutate}
|
||||||
isLoading={cancelBuildMutation.isLoading}
|
isLoading={cancelBuildMutation.isPending}
|
||||||
label="Cancel build"
|
label="Cancel build"
|
||||||
>
|
>
|
||||||
<BanIcon />
|
<BanIcon />
|
||||||
|
|||||||
@@ -94,10 +94,10 @@ export function useBatchActions(options: UseBatchActionsProps) {
|
|||||||
deleteAll: deleteAllMutation.mutateAsync,
|
deleteAll: deleteAllMutation.mutateAsync,
|
||||||
updateAll: updateAllMutation.mutateAsync,
|
updateAll: updateAllMutation.mutateAsync,
|
||||||
isLoading:
|
isLoading:
|
||||||
favoriteAllMutation.isLoading ||
|
favoriteAllMutation.isPending ||
|
||||||
unfavoriteAllMutation.isLoading ||
|
unfavoriteAllMutation.isPending ||
|
||||||
startAllMutation.isLoading ||
|
startAllMutation.isPending ||
|
||||||
stopAllMutation.isLoading ||
|
stopAllMutation.isPending ||
|
||||||
deleteAllMutation.isLoading,
|
deleteAllMutation.isPending,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,22 +22,14 @@ import {
|
|||||||
import themes, { DEFAULT_THEME } from "theme";
|
import themes, { DEFAULT_THEME } from "theme";
|
||||||
import { MockUserOwner } from "./entities";
|
import { MockUserOwner } from "./entities";
|
||||||
|
|
||||||
|
// Creates one query client for each test case, to make sure that tests are
|
||||||
|
// isolated and can't affect each other
|
||||||
export function createTestQueryClient() {
|
export function createTestQueryClient() {
|
||||||
// Helps create one query client for each test case, to make sure that tests
|
|
||||||
// are isolated and can't affect each other
|
|
||||||
return new QueryClient({
|
return new QueryClient({
|
||||||
logger: {
|
|
||||||
...console,
|
|
||||||
// Some tests are designed to throw errors as part of their functionality.
|
|
||||||
// To avoid unnecessary noise from these expected errors, the code is
|
|
||||||
// structured to suppress them. If this suppression becomes problematic,
|
|
||||||
// the code can be refactored to handle query errors on a per-test basis.
|
|
||||||
error: () => {},
|
|
||||||
},
|
|
||||||
defaultOptions: {
|
defaultOptions: {
|
||||||
queries: {
|
queries: {
|
||||||
retry: false,
|
retry: false,
|
||||||
cacheTime: 0,
|
gcTime: 0,
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
networkMode: "offlineFirst",
|
networkMode: "offlineFirst",
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user