diff --git a/website/commitlint.config.js b/website/commitlint.config.js index 422b19445b..3f5e287f9e 100644 --- a/website/commitlint.config.js +++ b/website/commitlint.config.js @@ -1 +1 @@ -module.exports = { extends: ['@commitlint/config-conventional'] }; +export default { extends: ['@commitlint/config-conventional'] }; diff --git a/website/package-lock.json b/website/package-lock.json index 67a4a3e244..21422e7879 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -11,7 +11,7 @@ "@astrojs/mdx": "^3.1.2", "@astrojs/node": "^8.3.2", "@emotion/react": "^11.11.4", - "@headlessui/react": "^1.7.19", + "@headlessui/react": "^2.1.1", "@mui/material": "~5.14.20", "@mui/x-date-pickers": "^6.19.7", "@svgr/core": "^8.1.0", @@ -78,6 +78,7 @@ "msw": "^2.3.1", "prettier": "3.3.2", "prettier-plugin-astro": "^0.14.0", + "resize-observer-polyfill": "^1.5.1", "sass": "^1.77.6", "tailwindcss": "^3.4.4", "typescript": "^5.5.2", @@ -1911,19 +1912,21 @@ "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==" }, "node_modules/@headlessui/react": { - "version": "1.7.19", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.19.tgz", - "integrity": "sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.1.1.tgz", + "integrity": "sha512-808gVNUbRDbDR3GMNPHy+ON0uvR8b9H7IA+Q2UbhOsNCIjgwuwb2Iuv8VPT/1AW0UzLX8g10tN6LhF15GaUJCQ==", "dependencies": { - "@tanstack/react-virtual": "^3.0.0-beta.60", - "client-only": "^0.0.1" + "@floating-ui/react": "^0.26.16", + "@react-aria/focus": "^3.17.1", + "@react-aria/interactions": "^3.21.3", + "@tanstack/react-virtual": "3.5.0" }, "engines": { "node": ">=10" }, "peerDependencies": { - "react": "^16 || ^17 || ^18", - "react-dom": "^16 || ^17 || ^18" + "react": "^18", + "react-dom": "^18" } }, "node_modules/@humanwhocodes/config-array": { @@ -3133,6 +3136,83 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@react-aria/focus": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.17.1.tgz", + "integrity": "sha512-FLTySoSNqX++u0nWZJPPN5etXY0WBxaIe/YuL/GTEeuqUIuC/2bJSaw5hlsM6T2yjy6Y/VAxBcKSdAFUlU6njQ==", + "dependencies": { + "@react-aria/interactions": "^3.21.3", + "@react-aria/utils": "^3.24.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/interactions": { + "version": "3.21.3", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.21.3.tgz", + "integrity": "sha512-BWIuf4qCs5FreDJ9AguawLVS0lV9UU+sK4CCnbCNNmYqOWY+1+gRXCsnOM32K+oMESBxilAjdHW5n1hsMqYMpA==", + "dependencies": { + "@react-aria/ssr": "^3.9.4", + "@react-aria/utils": "^3.24.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/ssr": { + "version": "3.9.4", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.4.tgz", + "integrity": "sha512-4jmAigVq409qcJvQyuorsmBR4+9r3+JEC60wC+Y0MZV0HCtTmm8D9guYXlJMdx0SSkgj0hHAyFm/HvPNFofCoQ==", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-aria/utils": { + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.24.1.tgz", + "integrity": "sha512-O3s9qhPMd6n42x9sKeJ3lhu5V1Tlnzhu6Yk8QOvDuXf7UGuUjXf9mzfHJt1dYzID4l9Fwm8toczBzPM9t0jc8Q==", + "dependencies": { + "@react-aria/ssr": "^3.9.4", + "@react-stately/utils": "^3.10.1", + "@react-types/shared": "^3.23.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-stately/utils": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-VS/EHRyicef25zDZcM/ClpzYMC5i2YGN6uegOeQawmgfGjb02yaCX0F0zR69Pod9m2Hr3wunTbtpgVXvYbZItg==", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@react-types/shared": { + "version": "3.23.1", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.23.1.tgz", + "integrity": "sha512-5d+3HbFDxGZjhbMBeFHRQhexMFt4pUce3okyRtUVKbbedQFUrtXSBg9VszgF2RTeQDKDkMCIQDtz5ccP/Lk1gw==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.13.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.0.tgz", @@ -3558,6 +3638,14 @@ "@svgr/core": "*" } }, + "node_modules/@swc/helpers": { + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.11.tgz", + "integrity": "sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A==", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@tailwindcss/forms": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.7.tgz", @@ -3644,11 +3732,11 @@ } }, "node_modules/@tanstack/react-virtual": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.1.2.tgz", - "integrity": "sha512-qibmxtctgOZo2I+3Rw5GR9kXgaa15U5r3/idDY1ItUKW15UK7GhCfyIfE6qYuJ1fxQF6dJDsD8SbpPyuJgpxuA==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.5.0.tgz", + "integrity": "sha512-rtvo7KwuIvqK9zb0VZ5IL7fiJAEnG+0EiFZz8FUOs+2mhGqdGmjKIaT1XU7Zq0eFqL0jonLlhbayJI/J2SA/Bw==", "dependencies": { - "@tanstack/virtual-core": "3.1.2" + "@tanstack/virtual-core": "3.5.0" }, "funding": { "type": "github", @@ -3660,9 +3748,9 @@ } }, "node_modules/@tanstack/virtual-core": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.1.2.tgz", - "integrity": "sha512-DATZJs8iejkIUqXZe6ruDAnjFo78BKnIIgqQZrc7CmEFqfLEN/TPD91n4hRfo6hpRB6xC00bwKxv7vdjFNEmOg==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.5.0.tgz", + "integrity": "sha512-KnPRCkQTyqhanNC0K63GBG3wA8I+D1fQuVnAvcBF8f13akOKeQp1gSbu6f77zCxhEk727iV5oQnbHLYzHrECLg==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" @@ -6098,11 +6186,6 @@ "node": ">= 12" } }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" - }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -12586,6 +12669,13 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", + "dev": true, + "license": "MIT" + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", diff --git a/website/package.json b/website/package.json index 15c127082f..d3d0cbc9af 100644 --- a/website/package.json +++ b/website/package.json @@ -23,7 +23,7 @@ "@astrojs/mdx": "^3.1.2", "@astrojs/node": "^8.3.2", "@emotion/react": "^11.11.4", - "@headlessui/react": "^1.7.19", + "@headlessui/react": "^2.1.1", "@mui/material": "~5.14.20", "@mui/x-date-pickers": "^6.19.7", "@svgr/core": "^8.1.0", @@ -90,6 +90,7 @@ "msw": "^2.3.1", "prettier": "3.3.2", "prettier-plugin-astro": "^0.14.0", + "resize-observer-polyfill": "^1.5.1", "sass": "^1.77.6", "tailwindcss": "^3.4.4", "typescript": "^5.5.2", diff --git a/website/src/components/Navigation/DocsMenu.tsx b/website/src/components/Navigation/DocsMenu.tsx index a823064a86..b5e28e701f 100644 --- a/website/src/components/Navigation/DocsMenu.tsx +++ b/website/src/components/Navigation/DocsMenu.tsx @@ -1,4 +1,4 @@ -import { Disclosure } from '@headlessui/react'; +import { Disclosure, DisclosureButton, DisclosurePanel } from '@headlessui/react'; import type { MDXInstance } from 'astro'; import React from 'react'; @@ -53,17 +53,17 @@ const DocsMenu: React.FC = ({ docsPages, currentPageUrl }) => {
Documentation
- + {open ? ( +
- +
    {Object.entries(groupedPages).map(([dir, pages]) => (
  • @@ -87,7 +87,7 @@ const DocsMenu: React.FC = ({ docsPages, currentPageUrl }) => {
  • ))}
-
+
diff --git a/website/src/components/SequenceDetailsPage/SequenceContainer.spec.tsx b/website/src/components/SequenceDetailsPage/SequenceContainer.spec.tsx index 4f1e160c37..0d975b3365 100644 --- a/website/src/components/SequenceDetailsPage/SequenceContainer.spec.tsx +++ b/website/src/components/SequenceDetailsPage/SequenceContainer.spec.tsx @@ -1,7 +1,6 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { render, screen, waitFor } from '@testing-library/react'; -import React from 'react'; -import { act } from 'react-dom/test-utils'; +import React, { act } from 'react'; import { beforeEach, describe, expect, test, vi } from 'vitest'; import { SequencesContainer } from './SequencesContainer.tsx'; diff --git a/website/src/pages/[organism]/index.astro b/website/src/pages/[organism]/index.astro index 8fd0c23b72..46379c6107 100644 --- a/website/src/pages/[organism]/index.astro +++ b/website/src/pages/[organism]/index.astro @@ -2,5 +2,5 @@ import { cleanOrganism } from '../../components/Navigation/cleanOrganism'; const { organism } = cleanOrganism(Astro.params.organism); -return Astro.redirect(`/${organism.key}/search`); +return Astro.redirect(`/${organism!.key}/search`); --- diff --git a/website/src/types/config.ts b/website/src/types/config.ts index 1f746d4426..46b87161d3 100644 --- a/website/src/types/config.ts +++ b/website/src/types/config.ts @@ -117,5 +117,5 @@ export const websiteConfig = z.object({ }); export type WebsiteConfig = z.infer; -export type FieldValues = Record; -export type SetAFieldValue = (fieldName: string, value: string | number) => void; +export type FieldValues = Record; +export type SetAFieldValue = (fieldName: string, value: string | number | null) => void; diff --git a/website/tests/pages/edit/edit.page.ts b/website/tests/pages/edit/edit.page.ts index dd03aafbd3..c0ab4e113e 100644 --- a/website/tests/pages/edit/edit.page.ts +++ b/website/tests/pages/edit/edit.page.ts @@ -6,11 +6,9 @@ import { baseUrl, dummyOrganism, expect } from '../../e2e.fixture'; export class EditPage { private readonly submitButton; - private readonly downloadButton; constructor(public readonly page: Page) { this.submitButton = this.page.getByRole('button', { name: 'Submit' }); - this.downloadButton = this.page.getByRole('button', { name: 'Download', exact: false }); } public async goto(accessionVersion: AccessionVersion) { diff --git a/website/tests/pages/search/index.spec.ts b/website/tests/pages/search/index.spec.ts index 436e4b3298..751ae6be5c 100644 --- a/website/tests/pages/search/index.spec.ts +++ b/website/tests/pages/search/index.spec.ts @@ -26,7 +26,7 @@ test.describe('The search page', () => { `${baseUrl}${routes.searchPage(dummyOrganism.key)}?accession=${testAccessionVersion}`, ); const accessionLink = searchPage.page.getByRole('link', { name: testAccessionVersion }); - await searchPage.page.getByText('Search returned 1 sequence'); + searchPage.page.getByText('Search returned 1 sequence'); await expect(accessionLink).toBeVisible(); const rowLocator = searchPage.page.locator('tr'); @@ -77,9 +77,9 @@ test.describe('The search page', () => { await searchPage.searchFor([{ name: 'country', filterValue: 'Switzerland' }]); await searchPage.page.locator('tr').first().waitFor(); - const rowLocator = await searchPage.page.locator('tr').getByText('Switzerland'); + const rowLocator = searchPage.page.locator('tr').getByText('Switzerland'); const rowCount = await rowLocator.count(); - await expect(rowCount).toBeGreaterThan(0); + expect(rowCount).toBeGreaterThan(0); }); test('should reset the search', async ({ searchPage }) => { diff --git a/website/tests/pages/search/search.page.ts b/website/tests/pages/search/search.page.ts index 39a9ab7c7c..10c5bce942 100644 --- a/website/tests/pages/search/search.page.ts +++ b/website/tests/pages/search/search.page.ts @@ -39,7 +39,7 @@ export class SearchPage { const accessions = []; for (let index = 1; index < 1 + elementsCount; index++) { - const element = await rowLocator.nth(index); + const element = rowLocator.nth(index); const innerText = await element.innerText(); accessions.push(innerText.split(' ')[0]); } diff --git a/website/vitest.setup.ts b/website/vitest.setup.ts index dcf83fa662..50748b02c5 100755 --- a/website/vitest.setup.ts +++ b/website/vitest.setup.ts @@ -4,7 +4,8 @@ import '@testing-library/jest-dom'; import { HttpStatusCode } from 'axios'; import { http } from 'msw'; import { setupServer } from 'msw/node'; -import { afterAll, afterEach, beforeAll, beforeEach } from 'vitest'; +import ResizeObserver from 'resize-observer-polyfill'; +import { afterAll, afterEach, beforeAll, beforeEach, vi } from 'vitest'; import type { GetSequencesResponse, Group, SequenceEntryToEdit, SubmissionIdMapping } from './src/types/backend.ts'; import type { DetailsResponse, InsertionsResponse, LapisError, MutationsResponse } from './src/types/lapis.ts'; @@ -33,6 +34,10 @@ export const testConfig = { backendKeycloakClientSecret: 'dummy', } as RuntimeConfig; +// Stubbing necessary since headlessui v2 +// See https://github.com/tailwindlabs/headlessui/issues/3268 +vi.stubGlobal('ResizeObserver', ResizeObserver); + export const metadataKey = 'originalMetaDataField'; export const editableEntry = 'originalMetaDataValue'; export const defaultReviewData: SequenceEntryToEdit = {