mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: remove circular dependencies (#17585)
I've been bit in the past by hard to deduce bugs caused by circular dependencies within TS projects. On a hunch that this could be contributing to some flaky tests I've used the tool [dpdm](https://github.com/acrazing/dpdm) to find and remove them. This PR does the following: - Move around exports/create new files to remove any non-type circular depencies - Add dpdm as a dev dependency and create the `check:circular-depency` pnpm script
This commit is contained in:
+3
-1
@@ -13,8 +13,9 @@
|
||||
"dev": "vite",
|
||||
"format": "biome format --write .",
|
||||
"format:check": "biome format .",
|
||||
"lint": "pnpm run lint:check && pnpm run lint:types",
|
||||
"lint": "pnpm run lint:check && pnpm run lint:types && pnpm run lint:circular-deps",
|
||||
"lint:check": " biome lint --error-on-warnings .",
|
||||
"lint:circular-deps": "dpdm --no-tree --no-warning -T ./src/App.tsx",
|
||||
"lint:fix": " biome lint --error-on-warnings --write .",
|
||||
"lint:types": "tsc -p .",
|
||||
"playwright:install": "playwright install --with-deps chromium",
|
||||
@@ -171,6 +172,7 @@
|
||||
"@vitejs/plugin-react": "4.3.4",
|
||||
"autoprefixer": "10.4.20",
|
||||
"chromatic": "11.25.2",
|
||||
"dpdm": "3.14.0",
|
||||
"express": "4.21.2",
|
||||
"jest": "29.7.0",
|
||||
"jest-canvas-mock": "2.5.2",
|
||||
|
||||
Generated
+97
@@ -422,6 +422,9 @@ importers:
|
||||
chromatic:
|
||||
specifier: 11.25.2
|
||||
version: 11.25.2
|
||||
dpdm:
|
||||
specifier: 3.14.0
|
||||
version: 3.14.0
|
||||
express:
|
||||
specifier: 4.21.2
|
||||
version: 4.21.2
|
||||
@@ -3223,6 +3226,14 @@ packages:
|
||||
classnames@2.3.2:
|
||||
resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==, tarball: https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz}
|
||||
|
||||
cli-cursor@3.1.0:
|
||||
resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==, tarball: https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
cli-spinners@2.9.2:
|
||||
resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==, tarball: https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
cli-width@4.1.0:
|
||||
resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==, tarball: https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz}
|
||||
engines: {node: '>= 12'}
|
||||
@@ -3231,6 +3242,10 @@ packages:
|
||||
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==, tarball: https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
clone@1.0.4:
|
||||
resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==, tarball: https://registry.npmjs.org/clone/-/clone-1.0.4.tgz}
|
||||
engines: {node: '>=0.8'}
|
||||
|
||||
clsx@2.1.1:
|
||||
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==, tarball: https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz}
|
||||
engines: {node: '>=6'}
|
||||
@@ -3491,6 +3506,9 @@ packages:
|
||||
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==, tarball: https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
defaults@1.0.4:
|
||||
resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==, tarball: https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz}
|
||||
|
||||
define-data-property@1.1.1:
|
||||
resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==, tarball: https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -3574,6 +3592,10 @@ packages:
|
||||
engines: {node: '>=12'}
|
||||
deprecated: Use your platform's native DOMException instead
|
||||
|
||||
dpdm@3.14.0:
|
||||
resolution: {integrity: sha512-YJzsFSyEtj88q5eTELg3UWU7TVZkG1dpbF4JDQ3t1b07xuzXmdoGeSz9TKOke1mUuOpWlk4q+pBh+aHzD6GBTg==, tarball: https://registry.npmjs.org/dpdm/-/dpdm-3.14.0.tgz}
|
||||
hasBin: true
|
||||
|
||||
dprint-node@1.0.8:
|
||||
resolution: {integrity: sha512-iVKnUtYfGrYcW1ZAlfR/F59cUVL8QIhWoBJoSjkkdua/dkWIgjZfiLMeTjiB06X0ZLkQ0M2C1VbUj/CxkIf1zg==, tarball: https://registry.npmjs.org/dprint-node/-/dprint-node-1.0.8.tgz}
|
||||
|
||||
@@ -4206,6 +4228,10 @@ packages:
|
||||
is-hexadecimal@2.0.1:
|
||||
resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==, tarball: https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz}
|
||||
|
||||
is-interactive@1.0.0:
|
||||
resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==, tarball: https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
is-map@2.0.2:
|
||||
resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==, tarball: https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz}
|
||||
|
||||
@@ -4261,6 +4287,10 @@ packages:
|
||||
resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==, tarball: https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
is-unicode-supported@0.1.0:
|
||||
resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==, tarball: https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
is-weakmap@2.0.1:
|
||||
resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==, tarball: https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz}
|
||||
|
||||
@@ -4598,6 +4628,10 @@ packages:
|
||||
lodash@4.17.21:
|
||||
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==, tarball: https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz}
|
||||
|
||||
log-symbols@4.1.0:
|
||||
resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==, tarball: https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
long@5.2.3:
|
||||
resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==, tarball: https://registry.npmjs.org/long/-/long-5.2.3.tgz}
|
||||
|
||||
@@ -5062,6 +5096,10 @@ packages:
|
||||
resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==, tarball: https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
||||
ora@5.4.1:
|
||||
resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==, tarball: https://registry.npmjs.org/ora/-/ora-5.4.1.tgz}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
outvariant@1.4.3:
|
||||
resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==, tarball: https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz}
|
||||
|
||||
@@ -5606,6 +5644,10 @@ packages:
|
||||
resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==, tarball: https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz}
|
||||
hasBin: true
|
||||
|
||||
restore-cursor@3.1.0:
|
||||
resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==, tarball: https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
reusify@1.0.4:
|
||||
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==, tarball: https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz}
|
||||
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
|
||||
@@ -6345,6 +6387,9 @@ packages:
|
||||
walker@1.0.8:
|
||||
resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==, tarball: https://registry.npmjs.org/walker/-/walker-1.0.8.tgz}
|
||||
|
||||
wcwidth@1.0.1:
|
||||
resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==, tarball: https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz}
|
||||
|
||||
webidl-conversions@7.0.0:
|
||||
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==, tarball: https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz}
|
||||
engines: {node: '>=12'}
|
||||
@@ -9422,6 +9467,12 @@ snapshots:
|
||||
|
||||
classnames@2.3.2: {}
|
||||
|
||||
cli-cursor@3.1.0:
|
||||
dependencies:
|
||||
restore-cursor: 3.1.0
|
||||
|
||||
cli-spinners@2.9.2: {}
|
||||
|
||||
cli-width@4.1.0: {}
|
||||
|
||||
cliui@8.0.1:
|
||||
@@ -9430,6 +9481,8 @@ snapshots:
|
||||
strip-ansi: 6.0.1
|
||||
wrap-ansi: 7.0.0
|
||||
|
||||
clone@1.0.4: {}
|
||||
|
||||
clsx@2.1.1: {}
|
||||
|
||||
cmdk@1.0.4(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
@@ -9667,6 +9720,10 @@ snapshots:
|
||||
|
||||
deepmerge@4.3.1: {}
|
||||
|
||||
defaults@1.0.4:
|
||||
dependencies:
|
||||
clone: 1.0.4
|
||||
|
||||
define-data-property@1.1.1:
|
||||
dependencies:
|
||||
get-intrinsic: 1.3.0
|
||||
@@ -9732,6 +9789,16 @@ snapshots:
|
||||
dependencies:
|
||||
webidl-conversions: 7.0.0
|
||||
|
||||
dpdm@3.14.0:
|
||||
dependencies:
|
||||
chalk: 4.1.2
|
||||
fs-extra: 11.2.0
|
||||
glob: 10.4.5
|
||||
ora: 5.4.1
|
||||
tslib: 2.8.1
|
||||
typescript: 5.6.3
|
||||
yargs: 17.7.2
|
||||
|
||||
dprint-node@1.0.8:
|
||||
dependencies:
|
||||
detect-libc: 1.0.3
|
||||
@@ -10473,6 +10540,8 @@ snapshots:
|
||||
|
||||
is-hexadecimal@2.0.1: {}
|
||||
|
||||
is-interactive@1.0.0: {}
|
||||
|
||||
is-map@2.0.2: {}
|
||||
|
||||
is-node-process@1.2.0: {}
|
||||
@@ -10522,6 +10591,8 @@ snapshots:
|
||||
dependencies:
|
||||
which-typed-array: 1.1.18
|
||||
|
||||
is-unicode-supported@0.1.0: {}
|
||||
|
||||
is-weakmap@2.0.1: {}
|
||||
|
||||
is-weakset@2.0.2:
|
||||
@@ -11096,6 +11167,11 @@ snapshots:
|
||||
|
||||
lodash@4.17.21: {}
|
||||
|
||||
log-symbols@4.1.0:
|
||||
dependencies:
|
||||
chalk: 4.1.2
|
||||
is-unicode-supported: 0.1.0
|
||||
|
||||
long@5.2.3: {}
|
||||
|
||||
longest-streak@3.1.0: {}
|
||||
@@ -11829,6 +11905,18 @@ snapshots:
|
||||
type-check: 0.4.0
|
||||
optional: true
|
||||
|
||||
ora@5.4.1:
|
||||
dependencies:
|
||||
bl: 4.1.0
|
||||
chalk: 4.1.2
|
||||
cli-cursor: 3.1.0
|
||||
cli-spinners: 2.9.2
|
||||
is-interactive: 1.0.0
|
||||
is-unicode-supported: 0.1.0
|
||||
log-symbols: 4.1.0
|
||||
strip-ansi: 6.0.1
|
||||
wcwidth: 1.0.1
|
||||
|
||||
outvariant@1.4.3: {}
|
||||
|
||||
p-limit@2.3.0:
|
||||
@@ -12441,6 +12529,11 @@ snapshots:
|
||||
path-parse: 1.0.7
|
||||
supports-preserve-symlinks-flag: 1.0.0
|
||||
|
||||
restore-cursor@3.1.0:
|
||||
dependencies:
|
||||
onetime: 5.1.2
|
||||
signal-exit: 3.0.7
|
||||
|
||||
reusify@1.0.4: {}
|
||||
|
||||
rimraf@3.0.2:
|
||||
@@ -13233,6 +13326,10 @@ snapshots:
|
||||
dependencies:
|
||||
makeerror: 1.0.12
|
||||
|
||||
wcwidth@1.0.1:
|
||||
dependencies:
|
||||
defaults: 1.0.4
|
||||
|
||||
webidl-conversions@7.0.0: {}
|
||||
|
||||
webpack-sources@3.2.3: {}
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
type SelectFilterOption,
|
||||
SelectFilterSearch,
|
||||
} from "components/Filter/SelectFilter";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import type { FC } from "react";
|
||||
import { type UseFilterMenuOptions, useFilterMenu } from "./menu";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { API } from "api/api";
|
||||
import { cachedQuery } from "api/queries/util";
|
||||
import type { Region, WorkspaceProxy } from "api/typesGenerated";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { useEmbeddedMetadata } from "hooks/useEmbeddedMetadata";
|
||||
import {
|
||||
type FC,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { renderHook, screen } from "@testing-library/react";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { http, HttpResponse } from "msw";
|
||||
import type { FC, PropsWithChildren } from "react";
|
||||
import { QueryClientProvider } from "react-query";
|
||||
@@ -9,7 +10,6 @@ import {
|
||||
} from "testHelpers/renderHelpers";
|
||||
import { server } from "testHelpers/server";
|
||||
import { AuthContext, type AuthContextValue } from "./AuthProvider";
|
||||
import { useAuthenticated } from "./RequireAuth";
|
||||
|
||||
describe("RequireAuth", () => {
|
||||
it("redirects to /login if user is not authenticated", async () => {
|
||||
|
||||
@@ -6,7 +6,7 @@ import { DashboardProvider as ProductionDashboardProvider } from "modules/dashbo
|
||||
import { type FC, useEffect } from "react";
|
||||
import { Navigate, Outlet, useLocation } from "react-router-dom";
|
||||
import { embedRedirect } from "utils/redirect";
|
||||
import { type AuthContextValue, useAuthContext } from "./AuthProvider";
|
||||
import { useAuthContext } from "./AuthProvider";
|
||||
|
||||
type RequireAuthProps = Readonly<{
|
||||
ProxyProvider?: typeof ProductionProxyProvider;
|
||||
@@ -81,28 +81,3 @@ export const RequireAuth: FC<RequireAuthProps> = ({
|
||||
</DashboardProvider>
|
||||
);
|
||||
};
|
||||
|
||||
type RequireKeys<T, R extends keyof T> = Omit<T, R> & {
|
||||
[K in keyof Pick<T, R>]-?: NonNullable<T[K]>;
|
||||
};
|
||||
|
||||
// We can do some TS magic here but I would rather to be explicit on what
|
||||
// values are not undefined when authenticated
|
||||
type AuthenticatedAuthContextValue = RequireKeys<
|
||||
AuthContextValue,
|
||||
"user" | "permissions"
|
||||
>;
|
||||
|
||||
export const useAuthenticated = (): AuthenticatedAuthContextValue => {
|
||||
const auth = useAuthContext();
|
||||
|
||||
if (!auth.user) {
|
||||
throw new Error("User is not authenticated.");
|
||||
}
|
||||
|
||||
if (!auth.permissions) {
|
||||
throw new Error("Permissions are not available.");
|
||||
}
|
||||
|
||||
return auth as AuthenticatedAuthContextValue;
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from "./useAuthenticated";
|
||||
export * from "./useClickable";
|
||||
export * from "./useClickableTableRow";
|
||||
export * from "./useClipboard";
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import {
|
||||
type AuthContextValue,
|
||||
useAuthContext,
|
||||
} from "contexts/auth/AuthProvider";
|
||||
|
||||
type RequireKeys<T, R extends keyof T> = Omit<T, R> & {
|
||||
[K in keyof Pick<T, R>]-?: NonNullable<T[K]>;
|
||||
};
|
||||
|
||||
// We can do some TS magic here but I would rather to be explicit on what
|
||||
// values are not undefined when authenticated
|
||||
type AuthenticatedAuthContextValue = RequireKeys<
|
||||
AuthContextValue,
|
||||
"user" | "permissions"
|
||||
>;
|
||||
|
||||
export const useAuthenticated = (): AuthenticatedAuthContextValue => {
|
||||
const auth = useAuthContext();
|
||||
|
||||
if (!auth.user) {
|
||||
throw new Error("User is not authenticated.");
|
||||
}
|
||||
|
||||
if (!auth.permissions) {
|
||||
throw new Error("Permissions are not available.");
|
||||
}
|
||||
|
||||
return auth as AuthenticatedAuthContextValue;
|
||||
};
|
||||
@@ -3,7 +3,7 @@ import Link from "@mui/material/Link";
|
||||
import Snackbar from "@mui/material/Snackbar";
|
||||
import { Button } from "components/Button/Button";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { AnnouncementBanners } from "modules/dashboard/AnnouncementBanners/AnnouncementBanners";
|
||||
import { LicenseBanner } from "modules/dashboard/LicenseBanner/LicenseBanner";
|
||||
import { type FC, type HTMLAttributes, Suspense } from "react";
|
||||
|
||||
@@ -10,7 +10,7 @@ import type {
|
||||
} from "api/typesGenerated";
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { useEmbeddedMetadata } from "hooks/useEmbeddedMetadata";
|
||||
import { canViewAnyOrganization } from "modules/permissions";
|
||||
import { type FC, type PropsWithChildren, createContext } from "react";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { health } from "api/queries/debug";
|
||||
import { deploymentStats } from "api/queries/deployment";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import type { FC } from "react";
|
||||
import { useQuery } from "react-query";
|
||||
import { DeploymentBannerView } from "./DeploymentBannerView";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { buildInfo } from "api/queries/buildInfo";
|
||||
import { useProxy } from "contexts/ProxyContext";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { useEmbeddedMetadata } from "hooks/useEmbeddedMetadata";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { canViewDeploymentSettings } from "modules/permissions";
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Button } from "components/Button/Button";
|
||||
import { displayError } from "components/GlobalSnackbar/utils";
|
||||
import { Latency } from "components/Latency/Latency";
|
||||
import type { ProxyContextValue } from "contexts/ProxyContext";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { ChevronDownIcon } from "lucide-react";
|
||||
import { type FC, useRef, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
BreadcrumbSeparator,
|
||||
} from "components/Breadcrumb/Breadcrumb";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { canViewDeploymentSettings } from "modules/permissions";
|
||||
import { RequirePermission } from "modules/permissions/RequirePermission";
|
||||
import { type FC, Suspense } from "react";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import type { FC } from "react";
|
||||
import { DeploymentSidebarView } from "./DeploymentSidebarView";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Sidebar as BaseSidebar } from "components/Sidebar/Sidebar";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { useOrganizationSettings } from "modules/management/OrganizationSettingsLayout";
|
||||
import type { FC } from "react";
|
||||
import { OrganizationSidebarView } from "./OrganizationSidebarView";
|
||||
|
||||
@@ -2,11 +2,12 @@ import { templateByName } from "api/queries/templates";
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { type FC, createContext } from "react";
|
||||
import type { FC } from "react";
|
||||
import { useQuery } from "react-query";
|
||||
import { useParams } from "react-router-dom";
|
||||
import CreateWorkspacePage from "./CreateWorkspacePage";
|
||||
import CreateWorkspacePageExperimental from "./CreateWorkspacePageExperimental";
|
||||
import { ExperimentalFormContext } from "./ExperimentalFormContext";
|
||||
|
||||
const CreateWorkspaceExperimentRouter: FC = () => {
|
||||
const { experiments } = useDashboard();
|
||||
@@ -70,7 +71,3 @@ const CreateWorkspaceExperimentRouter: FC = () => {
|
||||
export default CreateWorkspaceExperimentRouter;
|
||||
|
||||
const optOutKey = (id: string) => `parameters.${id}.optOut`;
|
||||
|
||||
export const ExperimentalFormContext = createContext<
|
||||
{ toggleOptedOut: () => void } | undefined
|
||||
>(undefined);
|
||||
|
||||
@@ -14,7 +14,7 @@ import type {
|
||||
Workspace,
|
||||
} from "api/typesGenerated";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { useEffectEvent } from "hooks/hookPolyfills";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName";
|
||||
|
||||
@@ -12,7 +12,7 @@ import type {
|
||||
Workspace,
|
||||
} from "api/typesGenerated";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { useEffectEvent } from "hooks/hookPolyfills";
|
||||
import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName";
|
||||
import {
|
||||
|
||||
@@ -47,11 +47,11 @@ import {
|
||||
useValidationSchemaForRichParameters,
|
||||
} from "utils/richParameters";
|
||||
import * as Yup from "yup";
|
||||
import { ExperimentalFormContext } from "./CreateWorkspaceExperimentRouter";
|
||||
import type {
|
||||
CreateWorkspaceMode,
|
||||
ExternalAuthPollingState,
|
||||
} from "./CreateWorkspacePage";
|
||||
import { ExperimentalFormContext } from "./ExperimentalFormContext";
|
||||
import { ExternalAuthButton } from "./ExternalAuthButton";
|
||||
import type { CreateWorkspacePermissions } from "./permissions";
|
||||
|
||||
|
||||
@@ -33,11 +33,11 @@ import {
|
||||
import { getFormHelpers, nameValidator } from "utils/formUtils";
|
||||
import type { AutofillBuildParameter } from "utils/richParameters";
|
||||
import * as Yup from "yup";
|
||||
import { ExperimentalFormContext } from "./CreateWorkspaceExperimentRouter";
|
||||
import type {
|
||||
CreateWorkspaceMode,
|
||||
ExternalAuthPollingState,
|
||||
} from "./CreateWorkspacePage";
|
||||
import { ExperimentalFormContext } from "./ExperimentalFormContext";
|
||||
import { ExternalAuthButton } from "./ExternalAuthButton";
|
||||
import type { CreateWorkspacePermissions } from "./permissions";
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { createContext } from "react";
|
||||
|
||||
export const ExperimentalFormContext = createContext<
|
||||
{ toggleOptedOut: () => void } | undefined
|
||||
>(undefined);
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
} from "components/GitDeviceAuth/GitDeviceAuth";
|
||||
import { SignInLayout } from "components/SignInLayout/SignInLayout";
|
||||
import { Welcome } from "components/Welcome/Welcome";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import type { FC } from "react";
|
||||
import { useMemo } from "react";
|
||||
import { useQuery, useQueryClient } from "react-query";
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
export const Language = {
|
||||
emailLabel: "Email",
|
||||
passwordLabel: "Password",
|
||||
emailInvalid: "Please enter a valid email address.",
|
||||
emailRequired: "Please enter an email address.",
|
||||
passwordSignIn: "Sign In",
|
||||
githubSignIn: "GitHub",
|
||||
oidcSignIn: "OpenID Connect",
|
||||
};
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
waitForLoaderToBeRemoved,
|
||||
} from "testHelpers/renderHelpers";
|
||||
import { server } from "testHelpers/server";
|
||||
import { Language } from "./Language";
|
||||
import { LoginPage } from "./LoginPage";
|
||||
import { Language } from "./SignInForm";
|
||||
|
||||
describe("LoginPage", () => {
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -4,7 +4,7 @@ import Button from "@mui/material/Button";
|
||||
import { visuallyHidden } from "@mui/utils";
|
||||
import type { AuthMethods } from "api/typesGenerated";
|
||||
import { type FC, useId } from "react";
|
||||
import { Language } from "./SignInForm";
|
||||
import { Language } from "./Language";
|
||||
|
||||
const iconStyles = {
|
||||
width: 16,
|
||||
|
||||
@@ -7,7 +7,7 @@ import type { FC } from "react";
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
import { getFormHelpers, onChangeTrimmed } from "utils/formUtils";
|
||||
import * as Yup from "yup";
|
||||
import { Language } from "./SignInForm";
|
||||
import { Language } from "./Language";
|
||||
|
||||
type PasswordSignInFormProps = {
|
||||
onSubmit: (credentials: { email: string; password: string }) => void;
|
||||
|
||||
@@ -7,16 +7,6 @@ import { getApplicationName } from "utils/appearance";
|
||||
import { OAuthSignInForm } from "./OAuthSignInForm";
|
||||
import { PasswordSignInForm } from "./PasswordSignInForm";
|
||||
|
||||
export const Language = {
|
||||
emailLabel: "Email",
|
||||
passwordLabel: "Password",
|
||||
emailInvalid: "Please enter a valid email address.",
|
||||
emailRequired: "Please enter an email address.",
|
||||
passwordSignIn: "Sign In",
|
||||
githubSignIn: "GitHub",
|
||||
oidcSignIn: "OpenID Connect",
|
||||
};
|
||||
|
||||
const styles = {
|
||||
root: {
|
||||
width: "100%",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createOrganization } from "api/queries/organizations";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
|
||||
import { RequirePermission } from "modules/permissions/RequirePermission";
|
||||
import type { FC } from "react";
|
||||
|
||||
@@ -13,7 +13,7 @@ import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog";
|
||||
import { EmptyState } from "components/EmptyState/EmptyState";
|
||||
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { usePaginatedQuery } from "hooks/usePaginatedQuery";
|
||||
import { useOrganizationSettings } from "modules/management/OrganizationSettingsLayout";
|
||||
import { RequirePermission } from "modules/permissions/RequirePermission";
|
||||
|
||||
@@ -5,7 +5,7 @@ import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { Margins } from "components/Margins/Margins";
|
||||
import { TabLink, Tabs, TabsList } from "components/Tabs/Tabs";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import {
|
||||
type WorkspacePermissions,
|
||||
workspacePermissionChecks,
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
templateVersion,
|
||||
templateVersionByName,
|
||||
} from "api/queries/templates";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { linkToTemplate, useLinks } from "modules/navigation";
|
||||
import { type FC, useMemo } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { workspacePermissionsByOrganization } from "api/queries/organizations";
|
||||
import { templateExamples, templates } from "api/queries/templates";
|
||||
import { useFilter } from "components/Filter/Filter";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import type { FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { groupsForUser } from "api/queries/groups";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { useAuthContext } from "contexts/auth/AuthProvider";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import type { FC } from "react";
|
||||
import { useQuery } from "react-query";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { Margins } from "components/Margins/Margins";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { type FC, Suspense } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { Outlet } from "react-router-dom";
|
||||
|
||||
@@ -22,7 +22,7 @@ import type {
|
||||
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import {
|
||||
castNotificationMethod,
|
||||
methodIcons,
|
||||
|
||||
@@ -2,7 +2,7 @@ import { getErrorMessage } from "api/errors";
|
||||
import { getApps, revokeApp } from "api/queries/oauth2";
|
||||
import { DeleteDialog } from "components/Dialogs/DeleteDialog/DeleteDialog";
|
||||
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { type FC, useState } from "react";
|
||||
import { useMutation, useQuery, useQueryClient } from "react-query";
|
||||
import { Section } from "../Section";
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import type { FC } from "react";
|
||||
import { useMutation, useQuery, useQueryClient } from "react-query";
|
||||
import { Section } from "../Section";
|
||||
|
||||
@@ -3,7 +3,7 @@ import { authMethods, updatePassword } from "api/queries/users";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import type { ComponentProps, FC } from "react";
|
||||
import { useMutation, useQuery } from "react-query";
|
||||
import { Section } from "../Section";
|
||||
|
||||
@@ -17,7 +17,7 @@ import { DeleteDialog } from "components/Dialogs/DeleteDialog/DeleteDialog";
|
||||
import { useFilter } from "components/Filter/Filter";
|
||||
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { isNonInitialPage } from "components/PaginationWidget/utils";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { usePaginatedQuery } from "hooks/usePaginatedQuery";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { type FC, useState } from "react";
|
||||
|
||||
@@ -22,8 +22,8 @@ import {
|
||||
import { displayError } from "components/GlobalSnackbar/utils";
|
||||
import { MemoizedInlineMarkdown } from "components/Markdown/Markdown";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import dayjs from "dayjs";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { useEmbeddedMetadata } from "hooks/useEmbeddedMetadata";
|
||||
import { useWorkspaceBuildLogs } from "hooks/useWorkspaceBuildLogs";
|
||||
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
|
||||
|
||||
@@ -3,7 +3,7 @@ import { templates } from "api/queries/templates";
|
||||
import type { Workspace } from "api/typesGenerated";
|
||||
import { useFilter } from "components/Filter/Filter";
|
||||
import { useUserFilterMenu } from "components/Filter/UserFilter";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useAuthenticated } from "hooks";
|
||||
import { useEffectEvent } from "hooks/hookPolyfills";
|
||||
import { usePagination } from "hooks/usePagination";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
|
||||
Reference in New Issue
Block a user