From 0f7c5de425553fd255c38026e84ac12d3729e540 Mon Sep 17 00:00:00 2001 From: SupaJoon Date: Tue, 28 May 2024 10:20:00 -0400 Subject: [PATCH 1/9] DEVPROD-6523: Patch Submission Filter (#130) --- .../integration/myPatches/my_patches.ts | 32 +++++++++++++- .../PatchesPage/RequesterSelector.tsx | 44 +++++++++++++++++++ .../PatchesPage/usePatchesQueryParams.ts | 7 ++- apps/spruce/src/constants/patch.ts | 2 + apps/spruce/src/pages/UserPatches.tsx | 2 + apps/spruce/src/types/patch.ts | 1 + 6 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 apps/spruce/src/components/PatchesPage/RequesterSelector.tsx diff --git a/apps/spruce/cypress/integration/myPatches/my_patches.ts b/apps/spruce/cypress/integration/myPatches/my_patches.ts index 4c1426623..2ca62b239 100644 --- a/apps/spruce/cypress/integration/myPatches/my_patches.ts +++ b/apps/spruce/cypress/integration/myPatches/my_patches.ts @@ -71,7 +71,37 @@ describe("My Patches Page", () => { "/version/5ecedafb562343215a7ff297/tasks?statuses=success", ); }); - + describe("Patch submission selctor", () => { + it("Clicking the patch submission selector updates the URL, and renders patches", () => { + cy.visit(MY_PATCHES_ROUTE); + cy.dataCy("requester-selector").click(); + const cliPatchTitle = "main: EVG-7823 add a commit queue message (#4048)"; + const prPatchTitle = + "evergreen-ci/evergreen' pull request #3186 by bsamek: EVG-7425 Don't send ShouldExit to unprovisioned hosts (https://github.com/evergreen-ci/evergreen/pull/3186)"; + cy.dataCy("patch-card").first().contains(cliPatchTitle); + cy.dataCy("github_pull_request-option").click(); + urlSearchParamsAreUpdated({ + pathname: MY_PATCHES_ROUTE, + paramName: "requesters", + search: "github_pull_request", + }); + cy.dataCy("patch-card").first().contains(prPatchTitle); + cy.dataCy("patch_request-option").click(); + urlSearchParamsAreUpdated({ + pathname: MY_PATCHES_ROUTE, + paramName: "requesters", + search: "github_pull_request,patch_request", + }); + cy.dataCy("patch-card").first().contains(cliPatchTitle); + cy.dataCy("github_pull_request-option").click(); + urlSearchParamsAreUpdated({ + pathname: MY_PATCHES_ROUTE, + paramName: "requesters", + search: "patch_request", + }); + cy.dataCy("patch-card").first().contains(cliPatchTitle); + }); + }); describe("Commit queue checkbox", () => { it("Clicking the commit queue checkbox updates the URL, requests patches and renders patches", () => { cy.visit(MY_PATCHES_ROUTE); diff --git a/apps/spruce/src/components/PatchesPage/RequesterSelector.tsx b/apps/spruce/src/components/PatchesPage/RequesterSelector.tsx new file mode 100644 index 000000000..3660a2d8c --- /dev/null +++ b/apps/spruce/src/components/PatchesPage/RequesterSelector.tsx @@ -0,0 +1,44 @@ +import { Combobox, ComboboxOption } from "@leafygreen-ui/combobox"; +import { githubPRRequester, patchRequester } from "constants/patch"; +import { requesterSubscriberOptions } from "constants/triggers"; +import { useStatusesFilter } from "hooks"; +import { PatchPageQueryParams } from "types/patch"; + +export const RequesterSelector: React.FC = () => { + const { inputValue: statusVal, setAndSubmitInputValue: statusValOnChange } = + useStatusesFilter({ urlParam: PatchPageQueryParams.Requesters }); + + return ( + + {options.map(({ displayName, key, value }) => ( + + ))} + + ); +}; + +const options = [ + { + displayName: requesterSubscriberOptions[githubPRRequester], + value: githubPRRequester, + key: githubPRRequester, + }, + { + displayName: requesterSubscriberOptions[patchRequester], + value: patchRequester, + key: patchRequester, + }, +]; diff --git a/apps/spruce/src/components/PatchesPage/usePatchesQueryParams.ts b/apps/spruce/src/components/PatchesPage/usePatchesQueryParams.ts index 4735de986..a8be2c442 100644 --- a/apps/spruce/src/components/PatchesPage/usePatchesQueryParams.ts +++ b/apps/spruce/src/components/PatchesPage/usePatchesQueryParams.ts @@ -13,13 +13,17 @@ import { PatchPageQueryParams, ALL_PATCH_STATUS } from "types/patch"; */ export const usePatchesQueryParams = (): Omit< Required, - "includeCommitQueue" | "onlyCommitQueue" | "requesters" + "includeCommitQueue" | "onlyCommitQueue" > => { const [patchName] = useQueryParam(PatchPageQueryParams.PatchName, ""); const [rawStatuses] = useQueryParam( PatchPageQueryParams.Statuses, [], ); + const [requesters] = useQueryParam( + PatchPageQueryParams.Requesters, + [], + ); const [hidden] = useQueryParam(PatchPageQueryParams.Hidden, false); const { limit, page } = usePagination(); const statuses = rawStatuses.filter((v) => v && v !== ALL_PATCH_STATUS); @@ -28,6 +32,7 @@ export const usePatchesQueryParams = (): Omit< includeHidden: hidden || Cookies.get(INCLUDE_HIDDEN_PATCHES) === "true", page, patchName: `${patchName}`, + requesters, statuses, }; }; diff --git a/apps/spruce/src/constants/patch.ts b/apps/spruce/src/constants/patch.ts index fec81a463..dd46fa17c 100644 --- a/apps/spruce/src/constants/patch.ts +++ b/apps/spruce/src/constants/patch.ts @@ -1,4 +1,6 @@ export const commitQueueAlias = "__commit_queue"; export const commitQueueRequester = "merge_test"; export const githubMergeRequester = "github_merge_request"; +export const githubPRRequester = "github_pull_request"; +export const patchRequester = "patch_request"; export const unlinkedPRUsers = new Set(["github_pull_request", "parent_patch"]); diff --git a/apps/spruce/src/pages/UserPatches.tsx b/apps/spruce/src/pages/UserPatches.tsx index c291a4f27..a64079064 100644 --- a/apps/spruce/src/pages/UserPatches.tsx +++ b/apps/spruce/src/pages/UserPatches.tsx @@ -3,6 +3,7 @@ import Cookies from "js-cookie"; import { useParams } from "react-router-dom"; import { useUserPatchesAnalytics } from "analytics"; import { PatchesPage } from "components/PatchesPage"; +import { RequesterSelector } from "components/PatchesPage/RequesterSelector"; import { usePatchesQueryParams } from "components/PatchesPage/usePatchesQueryParams"; import { INCLUDE_COMMIT_QUEUE_USER_PATCHES } from "constants/cookies"; import { DEFAULT_POLL_INTERVAL } from "constants/index"; @@ -52,6 +53,7 @@ export const UserPatches = () => { return ( } pageTitle={pageTitle} loading={loading && !data?.user.patches} pageType="user" diff --git a/apps/spruce/src/types/patch.ts b/apps/spruce/src/types/patch.ts index b7791275e..8aec3a15c 100644 --- a/apps/spruce/src/types/patch.ts +++ b/apps/spruce/src/types/patch.ts @@ -5,6 +5,7 @@ export enum PatchPageQueryParams { Page = "page", Limit = "limit", Hidden = "hidden", + Requesters = "requesters", } export enum PatchStatus { From b9a7c6d4b9e181cbf8c1e217c8e0eff0dd1d9e5e Mon Sep 17 00:00:00 2001 From: Sophie Stadler Date: Tue, 28 May 2024 11:31:10 -0400 Subject: [PATCH 2/9] DEVPROD-1120: Remove Babel deps and config (#137) --- apps/spruce/babel.config.js | 26 ---- apps/spruce/package.json | 6 - yarn.lock | 260 +++--------------------------------- 3 files changed, 19 insertions(+), 273 deletions(-) delete mode 100644 apps/spruce/babel.config.js diff --git a/apps/spruce/babel.config.js b/apps/spruce/babel.config.js deleted file mode 100644 index 29a6550d5..000000000 --- a/apps/spruce/babel.config.js +++ /dev/null @@ -1,26 +0,0 @@ -module.exports = { - presets: [ - "react-app", - [ - "@babel/preset-react", - { - runtime: "automatic", - importSource: "@emotion/react", - }, - ], - "@babel/preset-typescript", - ], - plugins: [ - [ - "import", - { - libraryName: "antd", - libraryDirectory: "lib", - style: "css", - }, - "antd", - ], - "@emotion/babel-plugin", - "import-graphql", - ], -}; diff --git a/apps/spruce/package.json b/apps/spruce/package.json index ff5c60644..76e8c30da 100644 --- a/apps/spruce/package.json +++ b/apps/spruce/package.json @@ -124,9 +124,6 @@ "react-virtuoso": "^4.7.10" }, "devDependencies": { - "@babel/plugin-proposal-private-property-in-object": "^7.17.12", - "@babel/preset-react": "^7.12.13", - "@babel/preset-typescript": "7.21.5", "@emotion/babel-plugin": "11.11.0", "@graphql-codegen/cli": "5.0.2", "@graphql-codegen/typescript": "4.0.1", @@ -154,10 +151,7 @@ "@types/react": "18.2.0", "@types/react-dom": "18.2.0", "@vitejs/plugin-react": "4.2.1", - "babel-loader": "^9.1.3", - "babel-plugin-import": "^1.13.6", "babel-plugin-import-graphql": "^2.8.1", - "babel-preset-react-app": "^10.0.1", "camelcase": "^6.1.0", "cypress": "12.17.1", "eslint": "8.56.0", diff --git a/yarn.lock b/yarn.lock index bce70bb17..647d6efa3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -143,7 +143,7 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.4.tgz#6f102372e9094f25d908ca0d34fc74c74606059a" integrity sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ== -"@babel/core@^7.11.6", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.13.16", "@babel/core@^7.14.0", "@babel/core@^7.16.0", "@babel/core@^7.18.5", "@babel/core@^7.18.9", "@babel/core@^7.20.12", "@babel/core@^7.22.9", "@babel/core@^7.23.0", "@babel/core@^7.23.2": +"@babel/core@^7.11.6", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.13.16", "@babel/core@^7.14.0", "@babel/core@^7.18.5", "@babel/core@^7.18.9", "@babel/core@^7.20.12", "@babel/core@^7.22.9", "@babel/core@^7.23.0", "@babel/core@^7.23.2": version "7.24.3" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.3.tgz#568864247ea10fbd4eff04dda1e05f9e2ea985c3" integrity sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ== @@ -205,7 +205,7 @@ "@jridgewell/trace-mapping" "^0.3.25" jsesc "^2.5.1" -"@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.22.5": +"@babel/helper-annotate-as-pure@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== @@ -230,7 +230,7 @@ lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0", "@babel/helper-create-class-features-plugin@^7.24.1": +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.24.1": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.1.tgz#db58bf57137b623b916e24874ab7188d93d7f68f" integrity sha512-1yJa9dX9g//V6fDebXoEfEsxkZHk3Hcbm+zLhyu6qVgYFLvmTALTeV+jNU9e5RnYtioBrGEOdoI2joMSNQ/+aA== @@ -292,7 +292,7 @@ dependencies: "@babel/types" "^7.23.0" -"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.22.15", "@babel/helper-module-imports@^7.24.1", "@babel/helper-module-imports@^7.24.3": +"@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.22.15", "@babel/helper-module-imports@^7.24.1", "@babel/helper-module-imports@^7.24.3": version "7.24.3" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz#6ac476e6d168c7c23ff3ba3cf4f7841d46ac8128" integrity sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg== @@ -317,7 +317,7 @@ dependencies: "@babel/types" "^7.22.5" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.21.5", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz#945681931a52f15ce879fd5b86ce2dae6d3d7f2a" integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w== @@ -376,7 +376,7 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz#918b1a7fa23056603506370089bd990d8720db62" integrity sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA== -"@babel/helper-validator-option@^7.21.0", "@babel/helper-validator-option@^7.23.5": +"@babel/helper-validator-option@^7.23.5": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== @@ -443,7 +443,7 @@ "@babel/helper-environment-visitor" "^7.22.20" "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-proposal-class-properties@^7.0.0", "@babel/plugin-proposal-class-properties@^7.13.0", "@babel/plugin-proposal-class-properties@^7.16.0": +"@babel/plugin-proposal-class-properties@^7.0.0", "@babel/plugin-proposal-class-properties@^7.13.0": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== @@ -451,16 +451,7 @@ "@babel/helper-create-class-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-proposal-decorators@^7.16.4": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.24.1.tgz#bab2b9e174a2680f0a80f341f3ec70f809f8bb4b" - integrity sha512-zPEvzFijn+hRvJuX2Vu3KbEBN39LN3f7tW3MQO2LsIs57B26KU+kUc82BdAktS1VCM6libzh45eKGI65lg0cpA== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.1" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-decorators" "^7.24.1" - -"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8", "@babel/plugin-proposal-nullish-coalescing-operator@^7.16.0": +"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== @@ -468,14 +459,6 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@babel/plugin-proposal-numeric-separator@^7.16.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75" - integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-proposal-object-rest-spread@^7.0.0": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz#aa662940ef425779c75534a5c41e9d936edc390a" @@ -487,7 +470,7 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-transform-parameters" "^7.20.7" -"@babel/plugin-proposal-optional-chaining@^7.13.12", "@babel/plugin-proposal-optional-chaining@^7.16.0": +"@babel/plugin-proposal-optional-chaining@^7.13.12": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz#886f5c8978deb7d30f678b2e24346b287234d3ea" integrity sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA== @@ -496,29 +479,11 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-proposal-private-methods@^7.16.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" - integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": version "7.21.0-placeholder-for-preset-env.2" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== -"@babel/plugin-proposal-private-property-in-object@^7.17.12": - version "7.21.11" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz#69d597086b6760c4126525cfa154f34631ff272c" - integrity sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-create-class-features-plugin" "^7.21.0" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" @@ -540,13 +505,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-decorators@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.24.1.tgz#71d9ad06063a6ac5430db126b5df48c70ee885fa" - integrity sha512-05RJdO/cCrtVWuAaSn1tS3bH8jbsJa/Y1uD186u6J4C/1mnHFxseeuWpsqr9anvo7TUulev7tm7GDwRV+VuhDw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-syntax-dynamic-import@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" @@ -596,7 +554,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.21.4", "@babel/plugin-syntax-jsx@^7.23.3", "@babel/plugin-syntax-jsx@^7.24.1": +"@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.23.3", "@babel/plugin-syntax-jsx@^7.24.1": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz#3f6ca04b8c841811dbc3c5c5f837934e0d626c10" integrity sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA== @@ -799,7 +757,7 @@ "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-transform-flow-strip-types@^7.0.0", "@babel/plugin-transform-flow-strip-types@^7.16.0", "@babel/plugin-transform-flow-strip-types@^7.24.1": +"@babel/plugin-transform-flow-strip-types@^7.0.0", "@babel/plugin-transform-flow-strip-types@^7.24.1": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.1.tgz#fa8d0a146506ea195da1671d38eed459242b2dcc" integrity sha512-iIYPIWt3dUmUKKE10s3W+jsQ3icFkw0JyRVyY1B7G4yK/nngAOHLVx8xlhA6b/Jzl/Y0nis8gjqhqKtRDQqHWQ== @@ -862,7 +820,7 @@ "@babel/helper-module-transforms" "^7.23.3" "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.13.8", "@babel/plugin-transform-modules-commonjs@^7.21.5", "@babel/plugin-transform-modules-commonjs@^7.23.0", "@babel/plugin-transform-modules-commonjs@^7.24.1": +"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.13.8", "@babel/plugin-transform-modules-commonjs@^7.23.0", "@babel/plugin-transform-modules-commonjs@^7.24.1": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz#e71ba1d0d69e049a22bf90b3867e263823d3f1b9" integrity sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw== @@ -987,20 +945,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-react-display-name@^7.0.0", "@babel/plugin-transform-react-display-name@^7.16.0", "@babel/plugin-transform-react-display-name@^7.24.1": +"@babel/plugin-transform-react-display-name@^7.0.0": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.1.tgz#554e3e1a25d181f040cf698b93fd289a03bfdcdb" integrity sha512-mvoQg2f9p2qlpDQRBC7M3c3XTr0k7cp/0+kFKKO/7Gtu0LSw16eKB+Fabe2bDT/UpsyasTBBkAnbdsLrkD5XMw== dependencies: "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-react-jsx-development@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz#e716b6edbef972a92165cd69d92f1255f7e73e87" - integrity sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A== - dependencies: - "@babel/plugin-transform-react-jsx" "^7.22.5" - "@babel/plugin-transform-react-jsx-self@^7.18.6": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.1.tgz#a21d866d8167e752c6a7c4555dba8afcdfce6268" @@ -1022,7 +973,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-react-jsx@^7.0.0", "@babel/plugin-transform-react-jsx@^7.22.5", "@babel/plugin-transform-react-jsx@^7.23.4": +"@babel/plugin-transform-react-jsx@^7.0.0": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz#393f99185110cea87184ea47bcb4a7b0c2e39312" integrity sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA== @@ -1033,14 +984,6 @@ "@babel/plugin-syntax-jsx" "^7.23.3" "@babel/types" "^7.23.4" -"@babel/plugin-transform-react-pure-annotations@^7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.1.tgz#c86bce22a53956331210d268e49a0ff06e392470" - integrity sha512-+pWEAaDJvSm9aFvJNpLiM2+ktl2Sn2U5DdyiWdZBxmLc6+xGt88dvFqsHiAiDS+8WqUwbDfkKz9jRxK3M0k+kA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/plugin-transform-regenerator@^7.24.1": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.1.tgz#625b7545bae52363bdc1fbbdc7252b5046409c8c" @@ -1056,18 +999,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-runtime@^7.16.4": - version "7.24.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.3.tgz#dc58ad4a31810a890550365cc922e1ff5acb5d7f" - integrity sha512-J0BuRPNlNqlMTRJ72eVptpt9VcInbxO6iP3jaxr+1NPhC0UkKL+6oeX6VXMEYdADnuqmMmsBspt4d5w8Y/TCbQ== - dependencies: - "@babel/helper-module-imports" "^7.24.3" - "@babel/helper-plugin-utils" "^7.24.0" - babel-plugin-polyfill-corejs2 "^0.4.10" - babel-plugin-polyfill-corejs3 "^0.10.1" - babel-plugin-polyfill-regenerator "^0.6.1" - semver "^6.3.1" - "@babel/plugin-transform-shorthand-properties@^7.0.0", "@babel/plugin-transform-shorthand-properties@^7.24.1": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.1.tgz#ba9a09144cf55d35ec6b93a32253becad8ee5b55" @@ -1104,7 +1035,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-typescript@^7.21.3", "@babel/plugin-transform-typescript@^7.24.1": +"@babel/plugin-transform-typescript@^7.24.1": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.1.tgz#5c05e28bb76c7dfe7d6c5bed9951324fd2d3ab07" integrity sha512-liYSESjX2fZ7JyBFkYG78nfvHlMKE6IpNdTVnxmlYUR+j5ZLsitFbaAE+eJSK2zPPkNWNw4mXL51rQ8WrvdK0w== @@ -1145,7 +1076,7 @@ "@babel/helper-create-regexp-features-plugin" "^7.22.15" "@babel/helper-plugin-utils" "^7.24.0" -"@babel/preset-env@^7.16.4", "@babel/preset-env@^7.22.9", "@babel/preset-env@^7.23.2": +"@babel/preset-env@^7.22.9", "@babel/preset-env@^7.23.2": version "7.24.3" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.24.3.tgz#f3f138c844ffeeac372597b29c51b5259e8323a3" integrity sha512-fSk430k5c2ff8536JcPvPWK4tZDwehWLGlBp0wrsBUjZVdeQV6lePbwKWZaZfK2vnh/1kQX1PzAJWsnBmVgGJA== @@ -1249,30 +1180,7 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-react@^7.12.13", "@babel/preset-react@^7.16.0": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.24.1.tgz#2450c2ac5cc498ef6101a6ca5474de251e33aa95" - integrity sha512-eFa8up2/8cZXLIpkafhaADTXSnl7IsUFCYenRWrARBz0/qZwcT0RBXpys0LJU4+WfPoF2ZG6ew6s2V6izMCwRA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-validator-option" "^7.23.5" - "@babel/plugin-transform-react-display-name" "^7.24.1" - "@babel/plugin-transform-react-jsx" "^7.23.4" - "@babel/plugin-transform-react-jsx-development" "^7.22.5" - "@babel/plugin-transform-react-pure-annotations" "^7.24.1" - -"@babel/preset-typescript@7.21.5": - version "7.21.5" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.21.5.tgz#68292c884b0e26070b4d66b202072d391358395f" - integrity sha512-iqe3sETat5EOrORXiQ6rWfoOg2y68Cs75B9wNxdPW4kixJxh7aXQE1KPdWLDniC24T/6dSnguF33W9j/ZZQcmA== - dependencies: - "@babel/helper-plugin-utils" "^7.21.5" - "@babel/helper-validator-option" "^7.21.0" - "@babel/plugin-syntax-jsx" "^7.21.4" - "@babel/plugin-transform-modules-commonjs" "^7.21.5" - "@babel/plugin-transform-typescript" "^7.21.3" - -"@babel/preset-typescript@^7.13.0", "@babel/preset-typescript@^7.16.0", "@babel/preset-typescript@^7.23.0": +"@babel/preset-typescript@^7.13.0", "@babel/preset-typescript@^7.23.0": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.24.1.tgz#89bdf13a3149a17b3b2a2c9c62547f06db8845ec" integrity sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ== @@ -1299,7 +1207,7 @@ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.0", "@babel/runtime@^7.20.7", "@babel/runtime@^7.23.2", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.0", "@babel/runtime@^7.20.7", "@babel/runtime@^7.23.2", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.24.1" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.1.tgz#431f9a794d173b53720e69a6464abc6f0e2a5c57" integrity sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ== @@ -7052,20 +6960,6 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv-formats@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" - integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== - dependencies: - ajv "^8.0.0" - -ajv-keywords@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" - integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== - dependencies: - fast-deep-equal "^3.1.3" - ajv@8.11.0: version "8.11.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f" @@ -7086,16 +6980,6 @@ ajv@^6.12.4, ajv@^6.7.0: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0, ajv@^8.9.0: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" - integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - ansi-align@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" @@ -7477,14 +7361,6 @@ babel-core@^7.0.0-bridge.0: resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== -babel-loader@^9.1.3: - version "9.1.3" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-9.1.3.tgz#3d0e01b4e69760cc694ee306fe16d358aa1c6f9a" - integrity sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw== - dependencies: - find-cache-dir "^4.0.0" - schema-utils "^4.0.0" - babel-plugin-import-graphql@2.8.1, babel-plugin-import-graphql@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/babel-plugin-import-graphql/-/babel-plugin-import-graphql-2.8.1.tgz#dec677dc47327181d69e8c451aff290460ca2ed6" @@ -7492,13 +7368,6 @@ babel-plugin-import-graphql@2.8.1, babel-plugin-import-graphql@^2.8.1: dependencies: graphql-tag "^2.9.2" -babel-plugin-import@^1.13.6: - version "1.13.8" - resolved "https://registry.yarnpkg.com/babel-plugin-import/-/babel-plugin-import-1.13.8.tgz#782c517f6bbf2de3b1f75aaafd6d20a491c4878c" - integrity sha512-36babpjra5m3gca44V6tSTomeBlPA7cHUynrE2WiQIm3rEGD9xy28MKsx5IdO45EbnpJY7Jrgd00C6Dwt/l/2Q== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - babel-plugin-istanbul@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" @@ -7528,7 +7397,7 @@ babel-plugin-polyfill-corejs2@^0.4.10: "@babel/helper-define-polyfill-provider" "^0.6.1" semver "^6.3.1" -babel-plugin-polyfill-corejs3@^0.10.1, babel-plugin-polyfill-corejs3@^0.10.4: +babel-plugin-polyfill-corejs3@^0.10.4: version "0.10.4" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz#789ac82405ad664c20476d0233b485281deb9c77" integrity sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg== @@ -7548,11 +7417,6 @@ babel-plugin-syntax-trailing-function-commas@^7.0.0-beta.0: resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz#aa213c1435e2bffeb6fca842287ef534ad05d5cf" integrity sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ== -babel-plugin-transform-react-remove-prop-types@^0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a" - integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA== - babel-preset-fbjs@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/babel-preset-fbjs/-/babel-preset-fbjs-3.4.0.tgz#38a14e5a7a3b285a3f3a86552d650dca5cf6111c" @@ -7586,28 +7450,6 @@ babel-preset-fbjs@^3.4.0: "@babel/plugin-transform-template-literals" "^7.0.0" babel-plugin-syntax-trailing-function-commas "^7.0.0-beta.0" -babel-preset-react-app@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz#ed6005a20a24f2c88521809fa9aea99903751584" - integrity sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg== - dependencies: - "@babel/core" "^7.16.0" - "@babel/plugin-proposal-class-properties" "^7.16.0" - "@babel/plugin-proposal-decorators" "^7.16.4" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.0" - "@babel/plugin-proposal-numeric-separator" "^7.16.0" - "@babel/plugin-proposal-optional-chaining" "^7.16.0" - "@babel/plugin-proposal-private-methods" "^7.16.0" - "@babel/plugin-transform-flow-strip-types" "^7.16.0" - "@babel/plugin-transform-react-display-name" "^7.16.0" - "@babel/plugin-transform-runtime" "^7.16.4" - "@babel/preset-env" "^7.16.4" - "@babel/preset-react" "^7.16.0" - "@babel/preset-typescript" "^7.16.0" - "@babel/runtime" "^7.16.3" - babel-plugin-macros "^3.1.0" - babel-plugin-transform-react-remove-prop-types "^0.4.24" - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -8192,11 +8034,6 @@ comment-parser@1.4.1: resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-1.4.1.tgz#bdafead37961ac079be11eb7ec65c4d021eaf9cc" integrity sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg== -common-path-prefix@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" - integrity sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w== - common-tags@1.8.2, common-tags@^1.8.0: version "1.8.2" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6" @@ -10029,14 +9866,6 @@ find-cache-dir@^3.0.0: make-dir "^3.0.2" pkg-dir "^4.1.0" -find-cache-dir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-4.0.0.tgz#a30ee0448f81a3990708f6453633c733e2f6eec2" - integrity sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg== - dependencies: - common-path-prefix "^3.0.0" - pkg-dir "^7.0.0" - find-root@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" @@ -10065,14 +9894,6 @@ find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" -find-up@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-6.3.0.tgz#2abab3d3280b2dc7ac10199ef324c4e002c8c790" - integrity sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw== - dependencies: - locate-path "^7.1.0" - path-exists "^5.0.0" - flat-cache@^3.0.4: version "3.2.0" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" @@ -11973,13 +11794,6 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -locate-path@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-7.2.0.tgz#69cb1779bd90b35ab1e771e1f2f89a202c2a8a8a" - integrity sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA== - dependencies: - p-locate "^6.0.0" - lodash-es@^4.17.15: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" @@ -12778,13 +12592,6 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-4.0.0.tgz#914af6544ed32bfa54670b061cafcbd04984b644" - integrity sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ== - dependencies: - yocto-queue "^1.0.0" - p-limit@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-5.0.0.tgz#6946d5b7140b649b7a33a027d89b4c625b3a5985" @@ -12813,13 +12620,6 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" -p-locate@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-6.0.0.tgz#3da9a49d4934b901089dca3302fa65dc5a05c04f" - integrity sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw== - dependencies: - p-limit "^4.0.0" - p-map@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" @@ -12914,11 +12714,6 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== -path-exists@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-5.0.0.tgz#a6aad9489200b21fab31e49cf09277e5116fb9e7" - integrity sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ== - path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -13067,13 +12862,6 @@ pkg-dir@^5.0.0: dependencies: find-up "^5.0.0" -pkg-dir@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-7.0.0.tgz#8f0c08d6df4476756c5ff29b3282d0bab7517d11" - integrity sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA== - dependencies: - find-up "^6.3.0" - pkg-types@^1.0.3, pkg-types@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.1.1.tgz#07b626880749beb607b0c817af63aac1845a73f2" @@ -14446,16 +14234,6 @@ scheduler@^0.23.0: dependencies: loose-envify "^1.1.0" -schema-utils@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" - integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== - dependencies: - "@types/json-schema" "^7.0.9" - ajv "^8.9.0" - ajv-formats "^2.1.1" - ajv-keywords "^5.1.0" - scroll-into-view-if-needed@^2.2.25: version "2.2.31" resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz#d3c482959dc483e37962d1521254e3295d0d1587" From c5dc5a668fe144e73a7cd698f07b0c434170d696 Mon Sep 17 00:00:00 2001 From: SupaJoon Date: Tue, 28 May 2024 12:59:21 -0400 Subject: [PATCH 3/9] DEVPROD-7502: Allow "evg-db-ops --reseed-and-dump" to run from app directories (#135) --- apps/parsley/package.json | 2 +- apps/spruce/package.json | 2 +- package.json | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/parsley/package.json b/apps/parsley/package.json index 647eab1ce..d7b925cbb 100644 --- a/apps/parsley/package.json +++ b/apps/parsley/package.json @@ -19,7 +19,7 @@ "deploy:prod": "env-cmd -e production ts-node scripts/deploy/run-deploy", "deploy:do-not-use": ". ./scripts/deploy/deploy.sh", "dev": "env-cmd -e devLocal -r .env-cmdrc.local.json vite", - "evg-db-ops": "yarn --cwd='../..' evg-db-ops", + "evg-db-ops": "../../scripts/evg-db-ops.sh", "staging": "env-cmd -e devStaging -r .env-cmdrc.local.json vite", "prod": "env-cmd -e devProduction -r .env-cmdrc.local.json vite", "eslint:fix": "yarn eslint:strict --fix", diff --git a/apps/spruce/package.json b/apps/spruce/package.json index 76e8c30da..9339f7a5c 100644 --- a/apps/spruce/package.json +++ b/apps/spruce/package.json @@ -25,7 +25,7 @@ "eslint:fix": "yarn eslint:strict --fix", "eslint:staged": "STRICT=1 eslint", "eslint:strict": "STRICT=1 eslint .", - "evg-db-ops": "yarn --cwd='../..' evg-db-ops", + "evg-db-ops": "../../scripts/evg-db-ops.sh", "prepare": "yarn --cwd='../..' prepare", "prettier-run": "prettier --write", "prod": "env-cmd -e devProduction -r .env-cmdrc.local.json yarn start", diff --git a/package.json b/package.json index bdb79b8cb..c99e1581c 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,6 @@ ] }, "scripts": { - "evg-db-ops": "./scripts/evg-db-ops.sh", "prepare": "husky", "test": "vitest --typecheck=false --exclude=./**/snapshot.test.ts" }, From 958c11afce607bb2f6eaba29843621699a241619 Mon Sep 17 00:00:00 2001 From: Arjun Patel Date: Tue, 28 May 2024 13:11:52 -0400 Subject: [PATCH 4/9] spruce/v4.1.22 --- apps/spruce/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/spruce/package.json b/apps/spruce/package.json index 9339f7a5c..3a445d2f0 100644 --- a/apps/spruce/package.json +++ b/apps/spruce/package.json @@ -1,6 +1,6 @@ { "name": "spruce", - "version": "4.1.21", + "version": "4.1.22", "private": true, "scripts": { "bootstrap-logkeeper": "./scripts/bootstrap-logkeeper.sh", From ed23d878a5fbf07826d5f8940eced0cc9e3329fd Mon Sep 17 00:00:00 2001 From: Sophie Stadler Date: Tue, 28 May 2024 18:01:12 -0400 Subject: [PATCH 5/9] DEVPROD-4198: Add prompt when pausing sleep-scheduled host (#133) --- README.md | 2 +- apps/parsley/src/gql/generated/types.ts | 29 +-- .../integration/projectSettings/access.ts | 1 + .../spruce/src/components/DayPicker/index.tsx | 10 +- .../Spawn/editHostModal/getFormSchema.tsx | 7 +- .../src/components/Spawn/getFormSchema.tsx | 17 +- apps/spruce/src/components/Spawn/index.tsx | 4 +- .../Spawn/spawnHostModal/getFormSchema.tsx | 7 +- .../components/Spawn/utils/hostUptime.test.ts | 125 +++++++---- .../src/components/Spawn/utils/hostUptime.ts | 201 +++++++++++------- .../src/components/Spawn/utils/index.ts | 5 +- .../SpruceForm/FieldTemplates/index.tsx | 3 +- apps/spruce/src/constants/fieldMaps.ts | 10 + apps/spruce/src/gql/generated/types.ts | 32 +-- apps/spruce/src/gql/mocks/getSpruceConfig.ts | 2 +- .../update-spawn-host-status.graphql | 7 +- .../spawn/spawnHost/EditSpawnHostButton.tsx | 1 + .../spawn/spawnHost/EditSpawnHostModal.tsx | 40 ++-- .../spawnHost/PauseSleepScheduleModal.tsx | 62 ++++++ .../spawn/spawnHost/SpawnHostActionButton.tsx | 56 +++-- .../spawnHost/SpawnHostTableActions.test.tsx | 179 +++++++++++++++- .../spawnHostButton/SpawnHostModal.tsx | 34 +-- apps/spruce/src/types/utils.ts | 3 + 23 files changed, 584 insertions(+), 253 deletions(-) create mode 100644 apps/spruce/src/pages/spawn/spawnHost/PauseSleepScheduleModal.tsx diff --git a/README.md b/README.md index 27837d521..40658a715 100644 --- a/README.md +++ b/README.md @@ -33,5 +33,5 @@ yarn test To run a particular workspace's unit tests from root: ```bash -yarn test --selectProjects [workspace-name] +yarn test --project [workspace-name] ``` diff --git a/apps/parsley/src/gql/generated/types.ts b/apps/parsley/src/gql/generated/types.ts index a2acfeaaf..2476c67d2 100644 --- a/apps/parsley/src/gql/generated/types.ts +++ b/apps/parsley/src/gql/generated/types.ts @@ -1091,8 +1091,7 @@ export type MutationAddAnnotationIssueArgs = { }; export type MutationAddFavoriteProjectArgs = { - identifier?: InputMaybe; - opts?: InputMaybe; + opts: AddFavoriteProjectInput; }; export type MutationAttachProjectToNewRepoArgs = { @@ -1135,16 +1134,11 @@ export type MutationCreatePublicKeyArgs = { }; export type MutationDeactivateStepbackTaskArgs = { - buildVariantName?: InputMaybe; - opts?: InputMaybe; - projectId?: InputMaybe; - taskName?: InputMaybe; + opts: DeactivateStepbackTaskInput; }; export type MutationDefaultSectionToRepoArgs = { - opts?: InputMaybe; - projectId?: InputMaybe; - section?: InputMaybe; + opts: DefaultSectionToRepoInput; }; export type MutationDeleteDistroArgs = { @@ -1204,9 +1198,7 @@ export type MutationOverrideTaskDependenciesArgs = { }; export type MutationPromoteVarsToRepoArgs = { - opts?: InputMaybe; - projectId?: InputMaybe; - varNames?: InputMaybe>; + opts: PromoteVarsToRepoInput; }; export type MutationRemoveAnnotationIssueArgs = { @@ -1217,8 +1209,7 @@ export type MutationRemoveAnnotationIssueArgs = { }; export type MutationRemoveFavoriteProjectArgs = { - identifier?: InputMaybe; - opts?: InputMaybe; + opts: RemoveFavoriteProjectInput; }; export type MutationRemoveItemFromCommitQueueArgs = { @@ -2095,14 +2086,12 @@ export type QueryProjectArgs = { export type QueryProjectEventsArgs = { before?: InputMaybe; - identifier?: InputMaybe; limit?: InputMaybe; - projectIdentifier?: InputMaybe; + projectIdentifier: Scalars["String"]["input"]; }; export type QueryProjectSettingsArgs = { - identifier?: InputMaybe; - projectIdentifier?: InputMaybe; + projectIdentifier: Scalars["String"]["input"]; }; export type QueryRepoEventsArgs = { @@ -2604,8 +2593,6 @@ export type Task = { status: Scalars["String"]["output"]; stepbackInfo?: Maybe; tags: Array; - /** @deprecated Use files instead */ - taskFiles: TaskFiles; taskGroup?: Maybe; taskGroupMaxHosts?: Maybe; /** taskLogs returns the tail 100 lines of the task's logs. */ @@ -2689,8 +2676,6 @@ export type TaskFiles = { /** TaskFilterOptions defines the parameters that are used when fetching tasks from a Version. */ export type TaskFilterOptions = { baseStatuses?: InputMaybe>; - /** @deprecated Use includeNeverActivatedTasks instead */ - includeEmptyActivation?: InputMaybe; includeNeverActivatedTasks?: InputMaybe; limit?: InputMaybe; page?: InputMaybe; diff --git a/apps/spruce/cypress/integration/projectSettings/access.ts b/apps/spruce/cypress/integration/projectSettings/access.ts index d50d0d1ab..831d6d898 100644 --- a/apps/spruce/cypress/integration/projectSettings/access.ts +++ b/apps/spruce/cypress/integration/projectSettings/access.ts @@ -38,6 +38,7 @@ describe("Access page", () => { cy.validateToast("success", "Successfully updated project"); // Assert persistence cy.reload(); + saveButtonEnabled(false); cy.get("@usernameInput").should("not.exist"); }); diff --git a/apps/spruce/src/components/DayPicker/index.tsx b/apps/spruce/src/components/DayPicker/index.tsx index f6b756c3d..1ec9fac0f 100644 --- a/apps/spruce/src/components/DayPicker/index.tsx +++ b/apps/spruce/src/components/DayPicker/index.tsx @@ -2,19 +2,11 @@ import { useCallback, useState } from "react"; import styled from "@emotion/styled"; import { palette } from "@leafygreen-ui/palette"; import { transitionDuration } from "@leafygreen-ui/tokens"; +import { days } from "constants/fieldMaps"; import { size } from "constants/tokens"; const { gray, white } = palette; -const days = [ - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", -]; const emptyState = new Array(days.length).fill(false); type DayPickerState = Array; diff --git a/apps/spruce/src/components/Spawn/editHostModal/getFormSchema.tsx b/apps/spruce/src/components/Spawn/editHostModal/getFormSchema.tsx index 10c20765c..cc992bee7 100644 --- a/apps/spruce/src/components/Spawn/editHostModal/getFormSchema.tsx +++ b/apps/spruce/src/components/Spawn/editHostModal/getFormSchema.tsx @@ -15,9 +15,8 @@ interface Props { canEditRdpPassword: boolean; canEditSshKeys: boolean; disableExpirationCheckbox: boolean; - hostUptimeValidation?: { + hostUptimeWarnings?: { enabledHoursCount: number; - errors: string[]; warnings: string[]; }; instanceTypes: string[]; @@ -32,7 +31,7 @@ export const getFormSchema = ({ canEditRdpPassword, canEditSshKeys, disableExpirationCheckbox, - hostUptimeValidation, + hostUptimeWarnings, instanceTypes, myPublicKeys, noExpirationCheckboxTooltip, @@ -41,7 +40,7 @@ export const getFormSchema = ({ }: Props): ReturnType => { const expirationDetails = getExpirationDetailsSchema({ disableExpirationCheckbox, - hostUptimeValidation, + hostUptimeWarnings, noExpirationCheckboxTooltip, timeZone, }); diff --git a/apps/spruce/src/components/Spawn/getFormSchema.tsx b/apps/spruce/src/components/Spawn/getFormSchema.tsx index a0723f14e..7a0b63051 100644 --- a/apps/spruce/src/components/Spawn/getFormSchema.tsx +++ b/apps/spruce/src/components/Spawn/getFormSchema.tsx @@ -16,16 +16,15 @@ import { const today = new Date(); type HostUptimeProps = { - hostUptimeValidation?: { + hostUptimeWarnings?: { enabledHoursCount: number; - errors: string[]; warnings: string[]; }; timeZone?: string; }; const getHostUptimeSchema = ({ - hostUptimeValidation, + hostUptimeWarnings, timeZone, }: HostUptimeProps) => ({ schema: { @@ -160,12 +159,11 @@ const getHostUptimeSchema = ({ "ui:descriptionNode": (
), "ui:showLabel": false, - "ui:warnings": hostUptimeValidation?.warnings, - "ui:errors": hostUptimeValidation?.errors, + "ui:warnings": hostUptimeWarnings?.warnings, }, }, }); @@ -183,9 +181,8 @@ const Details: React.FC<{ timeZone: string; totalUptimeHours: number }> = ({ type ExpirationProps = { disableExpirationCheckbox: boolean; - hostUptimeValidation?: { + hostUptimeWarnings?: { enabledHoursCount: number; - errors: string[]; warnings: string[]; }; noExpirationCheckboxTooltip?: string; @@ -194,12 +191,12 @@ type ExpirationProps = { export const getExpirationDetailsSchema = ({ disableExpirationCheckbox, - hostUptimeValidation, + hostUptimeWarnings, noExpirationCheckboxTooltip, timeZone, }: ExpirationProps) => { const defaultExpiration = getDefaultExpiration(); - const hostUptime = getHostUptimeSchema({ hostUptimeValidation, timeZone }); + const hostUptime = getHostUptimeSchema({ hostUptimeWarnings, timeZone }); return { schema: { title: "Expiration Details", diff --git a/apps/spruce/src/components/Spawn/index.tsx b/apps/spruce/src/components/Spawn/index.tsx index a0f4c22d7..93e365d81 100644 --- a/apps/spruce/src/components/Spawn/index.tsx +++ b/apps/spruce/src/components/Spawn/index.tsx @@ -3,7 +3,9 @@ export { DetailsCard } from "./DetailsCard"; export { MountVolumeSelect } from "./MountVolumeSelect"; export { defaultSleepSchedule, + getEnabledHoursCount, getHostUptimeFromGql, - validateUptimeSchedule, + getHostUptimeWarnings, + isNullSleepSchedule, validator, } from "./utils"; diff --git a/apps/spruce/src/components/Spawn/spawnHostModal/getFormSchema.tsx b/apps/spruce/src/components/Spawn/spawnHostModal/getFormSchema.tsx index 740cefa89..9ba434055 100644 --- a/apps/spruce/src/components/Spawn/spawnHostModal/getFormSchema.tsx +++ b/apps/spruce/src/components/Spawn/spawnHostModal/getFormSchema.tsx @@ -25,9 +25,8 @@ interface Props { isVirtualWorkStation: boolean; name?: string; }[]; - hostUptimeValidation?: { + hostUptimeWarnings?: { enabledHoursCount: number; - errors: string[]; warnings: string[]; }; isMigration: boolean; @@ -47,7 +46,7 @@ export const getFormSchema = ({ disableExpirationCheckbox, distroIdQueryParam, distros, - hostUptimeValidation, + hostUptimeWarnings, isMigration, isVirtualWorkstation, myPublicKeys, @@ -74,7 +73,7 @@ export const getFormSchema = ({ const expirationDetails = getExpirationDetailsSchema({ disableExpirationCheckbox, - hostUptimeValidation, + hostUptimeWarnings, noExpirationCheckboxTooltip, timeZone, }); diff --git a/apps/spruce/src/components/Spawn/utils/hostUptime.test.ts b/apps/spruce/src/components/Spawn/utils/hostUptime.test.ts index b99e877f2..0f176dd56 100644 --- a/apps/spruce/src/components/Spawn/utils/hostUptime.test.ts +++ b/apps/spruce/src/components/Spawn/utils/hostUptime.test.ts @@ -1,8 +1,9 @@ import { getHostUptimeFromGql, + getHostUptimeWarnings, + getNextHostStart, getSleepSchedule, matchesDefaultUptimeSchedule, - validateUptimeSchedule, validator, } from "./hostUptime"; @@ -81,7 +82,7 @@ describe("validator", () => { }, }, // @ts-expect-error - { expirationDetails: { hostUptime: { addError: f } } }, + { expirationDetails: { hostUptime: { details: { addError: f } } } }, ); expect(f).toHaveBeenCalledTimes(0); }); @@ -106,7 +107,7 @@ describe("validator", () => { }, }, // @ts-expect-error - { expirationDetails: { hostUptime: { addError: f } } }, + { expirationDetails: { hostUptime: { details: { addError: f } } } }, ); expect(f).toHaveBeenCalledTimes(1); }); @@ -131,7 +132,7 @@ describe("validator", () => { }, }, // @ts-expect-error - { expirationDetails: { hostUptime: { addError: f } } }, + { expirationDetails: { hostUptime: { details: { addError: f } } } }, ); expect(f).toHaveBeenCalledTimes(0); }); @@ -282,58 +283,100 @@ describe("getSleepSchedule", () => { }); }); -describe("validateUptimeSchedule", () => { +describe("getHostUptimeWarnings", () => { it("returns no errors when under recommended time", () => { expect( - validateUptimeSchedule({ - enabledWeekdays: [false, false, true, true, true, true, false], + getHostUptimeWarnings({ + enabledHoursCount: 60, + enabledWeekdaysCount: 5, runContinuously: false, - startTime: - "Sun Dec 31 1899 08:00:00 GMT+0000 (Coordinated Universal Time)", - stopTime: - "Sun Dec 31 1899 20:00:00 GMT+0000 (Coordinated Universal Time)", - useDefaultUptimeSchedule: true, }), - ).toStrictEqual({ - enabledHoursCount: 60, - errors: [], - warnings: [], - }); + ).toStrictEqual([]); }); it("returns a warning when over recommended time", () => { expect( - validateUptimeSchedule({ - enabledWeekdays: [false, true, true, true, true, true, true], + getHostUptimeWarnings({ + enabledHoursCount: 144, + enabledWeekdaysCount: 6, runContinuously: true, - startTime: - "Sun Dec 31 1899 08:00:00 GMT+0000 (Coordinated Universal Time)", - stopTime: - "Sun Dec 31 1899 20:00:00 GMT+0000 (Coordinated Universal Time)", - useDefaultUptimeSchedule: false, }), - ).toStrictEqual({ - enabledHoursCount: 144, - errors: [], - warnings: ["Consider pausing your host for 2 days per week."], - }); + ).toStrictEqual(["Consider pausing your host for 2 days per week."]); }); - it("returns an error when over allowed time", () => { + it("does not return a warning when over allowed time", () => { expect( - validateUptimeSchedule({ - enabledWeekdays: [true, true, true, true, true, true, true], + getHostUptimeWarnings({ + enabledHoursCount: 168, + enabledWeekdaysCount: 7, runContinuously: true, - startTime: - "Sun Dec 31 1899 08:00:00 GMT+0000 (Coordinated Universal Time)", - stopTime: - "Sun Dec 31 1899 20:00:00 GMT+0000 (Coordinated Universal Time)", - useDefaultUptimeSchedule: false, }), - ).toStrictEqual({ - enabledHoursCount: 168, - errors: ["Please pause your host for at least 1 day per week."], - warnings: [], + ).toStrictEqual([]); + }); +}); + +describe("getNextHostStart", () => { + it("calculates the next start with time", () => { + const sched = { + dailyStartTime: "08:00", + dailyStopTime: "20:00", + permanentlyExempt: true, + shouldKeepOff: true, + timeZone: "America/New_York", + wholeWeekdaysOff: [0, 6], + }; + const monday = new Date(null, null); + expect(getNextHostStart(sched, monday)).toStrictEqual({ + nextStartDay: "Tuesday", + nextStartTime: "8:00", + }); + }); + + it("calculates the next start with time when current day is off", () => { + const sched = { + dailyStartTime: "08:00", + dailyStopTime: "20:00", + permanentlyExempt: true, + shouldKeepOff: true, + timeZone: "America/New_York", + wholeWeekdaysOff: [0, 1, 6], + }; + const monday = new Date(null, null); + expect(getNextHostStart(sched, monday)).toStrictEqual({ + nextStartDay: "Tuesday", + nextStartTime: "8:00", + }); + }); + + it("calculates the next start when running continuously", () => { + const sched = { + dailyStartTime: "", + dailyStopTime: "", + permanentlyExempt: true, + shouldKeepOff: true, + timeZone: "America/New_York", + wholeWeekdaysOff: [0, 6], + }; + const monday = new Date(null, null); + expect(getNextHostStart(sched, monday)).toStrictEqual({ + nextStartDay: "Monday", + nextStartTime: null, + }); + }); + + it("calculates the next start when running continuously and current day is off", () => { + const sched = { + dailyStartTime: "", + dailyStopTime: "", + permanentlyExempt: true, + shouldKeepOff: true, + timeZone: "America/New_York", + wholeWeekdaysOff: [0, 1, 6], + }; + const monday = new Date(null, null); + expect(getNextHostStart(sched, monday)).toStrictEqual({ + nextStartDay: "Tuesday", + nextStartTime: null, }); }); }); diff --git a/apps/spruce/src/components/Spawn/utils/hostUptime.ts b/apps/spruce/src/components/Spawn/utils/hostUptime.ts index 8fe9a7f55..b8492ddba 100644 --- a/apps/spruce/src/components/Spawn/utils/hostUptime.ts +++ b/apps/spruce/src/components/Spawn/utils/hostUptime.ts @@ -1,7 +1,8 @@ -import { differenceInHours, parse } from "date-fns"; +import { differenceInHours, isTomorrow, parse } from "date-fns"; import { ValidateProps } from "components/SpruceForm"; -import { SleepScheduleInput } from "gql/generated/types"; -import { MyHost } from "types/spawn"; +import { days } from "constants/fieldMaps"; +import { SleepSchedule, SleepScheduleInput } from "gql/generated/types"; +import { Optional } from "types/utils"; import { arraySymmetricDifference } from "utils/array"; import { isProduction } from "utils/environmentVariables"; @@ -10,6 +11,7 @@ const hoursInDay = 24; const defaultStartHour = 8; const defaultStopHour = 20; const defaultScheduleWeeklyHourCount = 60; +const defaultScheduleWeekdaysCount = 5; const suggestedUptimeHours = (daysInWeek - 2) * hoursInDay; export const maxUptimeHours = (daysInWeek - 1) * hoursInDay; @@ -27,95 +29,67 @@ export type HostUptime = { runContinuously: boolean; }; }; + details?: null; }; type ValidateInput = { - enabledWeekdays: boolean[]; - stopTime: string; + enabledHoursCount: number; + enabledWeekdaysCount: number; runContinuously: boolean; - startTime: string; - useDefaultUptimeSchedule: boolean; }; -export const validateUptimeSchedule = ({ - enabledWeekdays, +export const getHostUptimeWarnings = ({ + enabledHoursCount, + enabledWeekdaysCount, runContinuously, - startTime, - stopTime, - useDefaultUptimeSchedule, -}: ValidateInput): { - enabledHoursCount: number; - errors: string[]; - warnings: string[]; -} => { - if (useDefaultUptimeSchedule) { - return { - enabledHoursCount: defaultScheduleWeeklyHourCount, - errors: [], - warnings: [], - }; - } - - const { enabledHoursCount, enabledWeekdaysCount } = getEnabledHoursCount({ - enabledWeekdays, - stopTime, - runContinuously, - startTime, - }); - +}: ValidateInput): string[] => { if (enabledHoursCount > maxUptimeHours) { - // Return error based on whether runContinously enabled - if (runContinuously) { - return { - enabledHoursCount, - errors: ["Please pause your host for at least 1 day per week."], - warnings: [], - }; - } - const hourlyRequirement = Math.floor(maxUptimeHours / enabledWeekdaysCount); - return { - enabledHoursCount, - errors: [ - `Please reduce your host uptime to a max of ${hourlyRequirement} hours per day.`, - ], - warnings: [], - }; + // This state represents an error, which is handled by the RJSF validator. + return []; } if (enabledHoursCount > suggestedUptimeHours) { // Return warning based on whether runContinuously enabled if (runContinuously) { - return { - enabledHoursCount, - errors: [], - warnings: ["Consider pausing your host for 2 days per week."], - }; + return ["Consider pausing your host for 2 days per week."]; } const hourlySuggestion = Math.floor( suggestedUptimeHours / enabledWeekdaysCount, ); - return { - enabledHoursCount, - errors: [], - warnings: [ - `Consider running your host for ${hourlySuggestion} hours per day or fewer.`, - ], - }; + return [ + `Consider running your host for ${hourlySuggestion} hours per day or fewer.`, + ]; } + // No error - return { - enabledHoursCount, - errors: [], - warnings: [], - }; + return []; }; -export const getEnabledHoursCount = ({ - enabledWeekdays, - runContinuously, - startTime, - stopTime, -}: Omit) => { +export const getEnabledHoursCount = ( + hostUptime: HostUptime, +): { enabledHoursCount: number; enabledWeekdaysCount: number } => { + if (!hostUptime) { + return { + enabledHoursCount: defaultScheduleWeeklyHourCount, + enabledWeekdaysCount: defaultScheduleWeekdaysCount, + }; + } + + const { + sleepSchedule: { + enabledWeekdays, + timeSelection: { runContinuously, startTime, stopTime }, + }, + useDefaultUptimeSchedule, + } = hostUptime; + + if (useDefaultUptimeSchedule) { + return { + enabledHoursCount: defaultScheduleWeeklyHourCount, + enabledWeekdaysCount: defaultScheduleWeekdaysCount, + }; + } + const enabledWeekdaysCount = enabledWeekdays?.filter((day) => day).length ?? 0; const enabledHoursCount = runContinuously @@ -165,17 +139,16 @@ const toTimeString = (date: Date): string => minute: "2-digit", }); -export const defaultSleepSchedule: Omit = { +export const defaultSleepSchedule: Optional = { dailyStartTime: toTimeString(defaultStartDate), dailyStopTime: toTimeString(defaultStopDate), permanentlyExempt: false, - // TODO: Add pause shouldKeepOff: false, wholeWeekdaysOff: [0, 6], }; export const getHostUptimeFromGql = ( - sleepSchedule: MyHost["sleepSchedule"], + sleepSchedule: Optional, ): HostUptime => { const { dailyStartTime, dailyStopTime, wholeWeekdaysOff } = sleepSchedule; @@ -210,7 +183,7 @@ export const getHostUptimeFromGql = ( }; export const matchesDefaultUptimeSchedule = ( - sleepSchedule: MyHost["sleepSchedule"], + sleepSchedule: Optional, ): boolean => { const { dailyStartTime, dailyStopTime, wholeWeekdaysOff } = sleepSchedule; @@ -235,22 +208,88 @@ export const validator = (({ expirationDetails }, errors) => { if (!hostUptime || noExpiration === false) return errors; const { sleepSchedule, useDefaultUptimeSchedule } = hostUptime; - const { enabledWeekdays, timeSelection } = sleepSchedule; + const { timeSelection } = sleepSchedule; if (useDefaultUptimeSchedule) { return errors; } - const { enabledHoursCount } = getEnabledHoursCount({ - enabledWeekdays, - ...timeSelection, - }); + const { enabledHoursCount, enabledWeekdaysCount } = + getEnabledHoursCount(hostUptime); if (enabledHoursCount > maxUptimeHours) { - errors.expirationDetails?.hostUptime?.addError("Insufficient hours"); + // Return error based on whether runContinously enabled + if (timeSelection?.runContinuously) { + // @ts-expect-error + errors.expirationDetails?.hostUptime?.details?.addError?.( + "Please pause your host for at least 1 day per week.", + ); + return errors; + } + const hourlyRequirement = Math.floor(maxUptimeHours / enabledWeekdaysCount); + // @ts-expect-error + errors.expirationDetails?.hostUptime?.details?.addError?.( + `Please reduce your host uptime to a max of ${hourlyRequirement} hours per day.`, + ); + return errors; } return errors; }) satisfies ValidateProps<{ expirationDetails?: { hostUptime?: HostUptime; noExpiration: boolean }; }>; + +/** + * isNullSleepSchedule indicates that the sleep schedule is unset. + * TODO: When sleep schedules are generally released, we should instead check whether noExpiration is set. + * Until then, noExpiration is insufficient because a user may have an unexpirable host running without a sleep schedule. + * @param sleepSchedule - sleepSchedule as returned from Evergreen + * @returns boolean indicating whether the sleep schedule is effectively unset. + */ +export const isNullSleepSchedule = ( + sleepSchedule: Optional, +) => { + if (!sleepSchedule) return true; + + const { dailyStartTime, dailyStopTime, wholeWeekdaysOff } = sleepSchedule; + if (dailyStartTime !== "") return false; + if (dailyStopTime !== "") return false; + if (arraySymmetricDifference(wholeWeekdaysOff, []).length > 0) return false; + return true; +}; + +export const getNextHostStart = ( + { dailyStartTime, wholeWeekdaysOff }: SleepSchedule, + todayDate: Date, +): { + nextStartDay: string; + nextStartTime: string | null; +} => { + if (dailyStartTime) { + const nextStartDate = parse(dailyStartTime, "HH:mm", todayDate); + do { + nextStartDate.setDate(nextStartDate.getDate() + 1); + } while (wholeWeekdaysOff.includes(nextStartDate.getDay())); + const nextStartDay: string = isTomorrow(nextStartDate) + ? "tomorrow" + : days[nextStartDate.getDay()]; + const nextStartTime: string = `${nextStartDate.getHours()}:${nextStartDate.getMinutes().toString().padStart(2, "0")}`; + return { nextStartDay, nextStartTime }; + } + + const nextStartDate = todayDate; + if (!wholeWeekdaysOff.includes(nextStartDate.getDay())) { + // Find the next planned off day in the schedule + do { + nextStartDate.setDate(nextStartDate.getDate() + 1); + } while (!wholeWeekdaysOff.includes(nextStartDate.getDay())); + } + // Find the first active day after that break + do { + nextStartDate.setDate(nextStartDate.getDate() + 1); + } while (wholeWeekdaysOff.includes(nextStartDate.getDay())); + const nextStartDay: string = isTomorrow(nextStartDate) + ? "tomorrow" + : days[nextStartDate.getDay()]; + return { nextStartDay, nextStartTime: null }; +}; diff --git a/apps/spruce/src/components/Spawn/utils/index.ts b/apps/spruce/src/components/Spawn/utils/index.ts index 97ce3b90b..81be4dac3 100644 --- a/apps/spruce/src/components/Spawn/utils/index.ts +++ b/apps/spruce/src/components/Spawn/utils/index.ts @@ -6,9 +6,12 @@ export { defaultSleepSchedule, defaultStartDate, defaultStopDate, + getEnabledHoursCount, getHostUptimeFromGql, + getHostUptimeWarnings, + getNextHostStart, getSleepSchedule, - validateUptimeSchedule, + isNullSleepSchedule, validator, } from "./hostUptime"; export type { HostUptime } from "./hostUptime"; diff --git a/apps/spruce/src/components/SpruceForm/FieldTemplates/index.tsx b/apps/spruce/src/components/SpruceForm/FieldTemplates/index.tsx index 53af4b31a..9a6165e68 100644 --- a/apps/spruce/src/components/SpruceForm/FieldTemplates/index.tsx +++ b/apps/spruce/src/components/SpruceForm/FieldTemplates/index.tsx @@ -18,6 +18,7 @@ export const DefaultFieldTemplate: React.FC = ({ hidden, id, label, + rawErrors, schema, uiSchema, }) => { @@ -27,7 +28,7 @@ export const DefaultFieldTemplate: React.FC = ({ const showLabel = uiSchema["ui:showLabel"] ?? true; const fieldDataCy = uiSchema["ui:field-data-cy"]; const descriptionNode = uiSchema["ui:descriptionNode"]; - const errors = uiSchema["ui:errors"] ?? []; + const errors = uiSchema["ui:errors"] ?? (rawErrors?.length ? rawErrors : []); const warnings = uiSchema["ui:warnings"] ?? []; return ( !hidden && ( diff --git a/apps/spruce/src/constants/fieldMaps.ts b/apps/spruce/src/constants/fieldMaps.ts index 3020dece9..3fd45e10f 100644 --- a/apps/spruce/src/constants/fieldMaps.ts +++ b/apps/spruce/src/constants/fieldMaps.ts @@ -195,3 +195,13 @@ export const notificationFields = { buildBreak: "Build break", commitQueue: "Commit queue", }; + +export const days = [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", +]; diff --git a/apps/spruce/src/gql/generated/types.ts b/apps/spruce/src/gql/generated/types.ts index ff10acba4..58a5c5940 100644 --- a/apps/spruce/src/gql/generated/types.ts +++ b/apps/spruce/src/gql/generated/types.ts @@ -1091,8 +1091,7 @@ export type MutationAddAnnotationIssueArgs = { }; export type MutationAddFavoriteProjectArgs = { - identifier?: InputMaybe; - opts?: InputMaybe; + opts: AddFavoriteProjectInput; }; export type MutationAttachProjectToNewRepoArgs = { @@ -1135,16 +1134,11 @@ export type MutationCreatePublicKeyArgs = { }; export type MutationDeactivateStepbackTaskArgs = { - buildVariantName?: InputMaybe; - opts?: InputMaybe; - projectId?: InputMaybe; - taskName?: InputMaybe; + opts: DeactivateStepbackTaskInput; }; export type MutationDefaultSectionToRepoArgs = { - opts?: InputMaybe; - projectId?: InputMaybe; - section?: InputMaybe; + opts: DefaultSectionToRepoInput; }; export type MutationDeleteDistroArgs = { @@ -1204,9 +1198,7 @@ export type MutationOverrideTaskDependenciesArgs = { }; export type MutationPromoteVarsToRepoArgs = { - opts?: InputMaybe; - projectId?: InputMaybe; - varNames?: InputMaybe>; + opts: PromoteVarsToRepoInput; }; export type MutationRemoveAnnotationIssueArgs = { @@ -1217,8 +1209,7 @@ export type MutationRemoveAnnotationIssueArgs = { }; export type MutationRemoveFavoriteProjectArgs = { - identifier?: InputMaybe; - opts?: InputMaybe; + opts: RemoveFavoriteProjectInput; }; export type MutationRemoveItemFromCommitQueueArgs = { @@ -2095,14 +2086,12 @@ export type QueryProjectArgs = { export type QueryProjectEventsArgs = { before?: InputMaybe; - identifier?: InputMaybe; limit?: InputMaybe; - projectIdentifier?: InputMaybe; + projectIdentifier: Scalars["String"]["input"]; }; export type QueryProjectSettingsArgs = { - identifier?: InputMaybe; - projectIdentifier?: InputMaybe; + projectIdentifier: Scalars["String"]["input"]; }; export type QueryRepoEventsArgs = { @@ -2604,8 +2593,6 @@ export type Task = { status: Scalars["String"]["output"]; stepbackInfo?: Maybe; tags: Array; - /** @deprecated Use files instead */ - taskFiles: TaskFiles; taskGroup?: Maybe; taskGroupMaxHosts?: Maybe; /** taskLogs returns the tail 100 lines of the task's logs. */ @@ -2689,8 +2676,6 @@ export type TaskFiles = { /** TaskFilterOptions defines the parameters that are used when fetching tasks from a Version. */ export type TaskFilterOptions = { baseStatuses?: InputMaybe>; - /** @deprecated Use includeNeverActivatedTasks instead */ - includeEmptyActivation?: InputMaybe; includeNeverActivatedTasks?: InputMaybe; limit?: InputMaybe; page?: InputMaybe; @@ -5322,8 +5307,7 @@ export type UpdatePublicKeyMutation = { }; export type UpdateSpawnHostStatusMutationVariables = Exact<{ - hostId: Scalars["String"]["input"]; - action: SpawnHostStatusActions; + updateSpawnHostStatusInput: UpdateSpawnHostStatusInput; }>; export type UpdateSpawnHostStatusMutation = { diff --git a/apps/spruce/src/gql/mocks/getSpruceConfig.ts b/apps/spruce/src/gql/mocks/getSpruceConfig.ts index 2f88dacf5..107926e19 100644 --- a/apps/spruce/src/gql/mocks/getSpruceConfig.ts +++ b/apps/spruce/src/gql/mocks/getSpruceConfig.ts @@ -74,7 +74,7 @@ export const getUserSettingsMock: ApolloMock< data: { userSettings: { __typename: "UserSettings", - dateFormat: "MM/DD/YYYY", + dateFormat: "MM/dd/yyyy", githubUser: { lastKnownAs: "user", __typename: "GithubUser", diff --git a/apps/spruce/src/gql/mutations/update-spawn-host-status.graphql b/apps/spruce/src/gql/mutations/update-spawn-host-status.graphql index 3568b6132..5b33bec7c 100644 --- a/apps/spruce/src/gql/mutations/update-spawn-host-status.graphql +++ b/apps/spruce/src/gql/mutations/update-spawn-host-status.graphql @@ -1,8 +1,9 @@ mutation UpdateSpawnHostStatus( - $hostId: String! - $action: SpawnHostStatusActions! + $updateSpawnHostStatusInput: UpdateSpawnHostStatusInput! ) { - updateSpawnHostStatus(hostId: $hostId, action: $action) { + updateSpawnHostStatus( + updateSpawnHostStatusInput: $updateSpawnHostStatusInput + ) { id status } diff --git a/apps/spruce/src/pages/spawn/spawnHost/EditSpawnHostButton.tsx b/apps/spruce/src/pages/spawn/spawnHost/EditSpawnHostButton.tsx index c73ff0d28..da22a7244 100644 --- a/apps/spruce/src/pages/spawn/spawnHost/EditSpawnHostButton.tsx +++ b/apps/spruce/src/pages/spawn/spawnHost/EditSpawnHostButton.tsx @@ -33,6 +33,7 @@ export const EditSpawnHostButton: React.FC = ({ trigger={