From 4c6c603d00336d1fd44d530b35ec796b7f1bb02d Mon Sep 17 00:00:00 2001 From: yannis Date: Thu, 11 Jun 2026 12:42:15 +0300 Subject: [PATCH 01/16] refactor(client): move pages routes into new router file --- packages/client/app/Pages.jsx | 80 +------------------ packages/client/app/Router.tsx | 52 ++++++++++++ .../components/AcceptArticleOwnershipPage.jsx | 8 +- .../DeclineArticleOwnershipPage.jsx | 8 +- .../component-frontpage/src/GroupPage.jsx | 4 +- .../components/component-login/src/Login.jsx | 13 ++- .../components/ArticleArtifactPage.jsx | 11 ++- .../client/app/pages/GroupWrapper.page.tsx | 38 +++++++++ packages/client/app/pages/index.ts | 1 + 9 files changed, 120 insertions(+), 95 deletions(-) create mode 100644 packages/client/app/Router.tsx create mode 100644 packages/client/app/pages/GroupWrapper.page.tsx create mode 100644 packages/client/app/pages/index.ts diff --git a/packages/client/app/Pages.jsx b/packages/client/app/Pages.jsx index b0a8d72d8..d61018661 100644 --- a/packages/client/app/Pages.jsx +++ b/packages/client/app/Pages.jsx @@ -1,7 +1,7 @@ /* eslint-disable react-hooks/exhaustive-deps */ import { useEffect } from 'react' -import { Route, Routes, useLocation, Navigate } from 'react-router-dom' +import { useLocation } from 'react-router-dom' import styled from 'styled-components' import { useQuery } from '@apollo/client/react' @@ -17,20 +17,15 @@ import DynamicFavicon from './dynamicFavicon' import { GET_GROUPS } from './queries' -import Login from './components/component-login/src' -import ArticleArtifactPage from './components/component-published-artifact/components/ArticleArtifactPage' -import DeclineArticleOwnershipPage from './components/component-dashboard/src/components/DeclineArticleOwnershipPage' -import AcceptArticleOwnershipPage from './components/component-dashboard/src/components/AcceptArticleOwnershipPage' -import InvitationAcceptedPage from './components/component-dashboard/src/components/InvitationAcceptedPage' import AssetManager from './components/asset-manager/src/AssetManagerPage' -import AdminPage from './components/AdminPage' -import GroupPage from './components/component-frontpage/src/GroupPage' import { JournalProvider } from './components/xpub-journal' import journal from '../config/journal' import ModalProvider from './components/asset-manager/src/ui/Modal/ModalProvider' import { XpubProvider } from './components/xpub-with-context/src' import { reloadTranslationsForGroup } from './i18n' +import Router from './Router' + const Container = styled.div` display: grid; height: 10vh; @@ -63,14 +58,8 @@ const Pages = () => { const groups = data?.groups ? data.groups : [] - const hasMultipleGroups = groups && groups.length > 1 - let onlyGroupName = '' let currentGroup = null - if (!hasMultipleGroups) { - onlyGroupName = groups[0]?.name - } - const name = location.pathname.split('/')[1] if (name) { @@ -123,8 +112,6 @@ const Pages = () => { config?.groupIdentity?.secondaryColor, ) - const { urlFrag } = config - return ( @@ -134,66 +121,7 @@ const Pages = () => { - - {hasMultipleGroups ? ( - } path="/" /> - ) : ( - - } - path="/" - /> - )} - - - } - path="/login" - /> - - - } - path={urlFrag} - /> - - {/* } path={`${urlFrag}`} /> */} - {/* } path="/" /> */} - - } path={`${urlFrag}/login`} /> - - } - path={`${urlFrag}/versions/:version/artifacts/:artifactId`} - /> - } - path={`${urlFrag}/decline/:invitationId`} - /> - } - path={`${urlFrag}/acceptarticle/:invitationId`} - /> - } - path={`${urlFrag}/invitation/accepted`} - /> - {/* AdminPage has nested routes within */} - } path={`${urlFrag}/*`} /> - + diff --git a/packages/client/app/Router.tsx b/packages/client/app/Router.tsx new file mode 100644 index 000000000..682c3094c --- /dev/null +++ b/packages/client/app/Router.tsx @@ -0,0 +1,52 @@ +import { type ReactNode } from 'react' +import { Route, Routes, Navigate } from 'react-router-dom' + +import AcceptArticleOwnershipPage from './components/component-dashboard/src/components/AcceptArticleOwnershipPage' +import ArticleArtifactPage from './components/component-published-artifact/components/ArticleArtifactPage' +import DeclineArticleOwnershipPage from './components/component-dashboard/src/components/DeclineArticleOwnershipPage' +import GroupPage from './components/component-frontpage/src/GroupPage' +import InvitationAcceptedPage from './components/component-dashboard/src/components/InvitationAcceptedPage' +import Login from './components/component-login/src' + +import { GroupWrapperPage } from './pages' + +import AdminPage from './components/AdminPage' + +const Router = (): ReactNode => { + return ( + + } path="/" /> + + } path="/:groupName"> + } index /> + } path="login" /> + + {/* Invitations */} + } + path="decline/:invitationId" + /> + + } + path="acceptarticle/:invitationId" + /> + + } + path="invitation/accepted" + /> + + } + path={`versions/:version/artifacts/:artifactId`} + /> + + {/* AdminPage has nested routes within */} + } path="*" /> + + + ) +} + +export default Router diff --git a/packages/client/app/components/component-dashboard/src/components/AcceptArticleOwnershipPage.jsx b/packages/client/app/components/component-dashboard/src/components/AcceptArticleOwnershipPage.jsx index 8dee711c1..49b87a32c 100644 --- a/packages/client/app/components/component-dashboard/src/components/AcceptArticleOwnershipPage.jsx +++ b/packages/client/app/components/component-dashboard/src/components/AcceptArticleOwnershipPage.jsx @@ -1,7 +1,5 @@ -/* eslint-disable react/prop-types */ - import { useContext } from 'react' -import { Navigate } from 'react-router-dom' +import { Navigate, useParams } from 'react-router-dom' import { useQuery } from '@apollo/client/react' import { useTranslation } from 'react-i18next' import { Container } from '../../../shared' @@ -9,10 +7,10 @@ import { GET_INVITATION_STATUS } from '../../../../queries' import { ConfigContext } from '../../../config/src' import InvitationError from './InvitationError' -const AcceptArticleOwnershipPage = ({ match }) => { +const AcceptArticleOwnershipPage = () => { const config = useContext(ConfigContext) const { t } = useTranslation() - const { invitationId } = match.params + const { invitationId } = useParams() const { urlFrag } = config const { loading, data, error } = useQuery(GET_INVITATION_STATUS, { diff --git a/packages/client/app/components/component-dashboard/src/components/DeclineArticleOwnershipPage.jsx b/packages/client/app/components/component-dashboard/src/components/DeclineArticleOwnershipPage.jsx index f7969d95b..9fc0883c9 100644 --- a/packages/client/app/components/component-dashboard/src/components/DeclineArticleOwnershipPage.jsx +++ b/packages/client/app/components/component-dashboard/src/components/DeclineArticleOwnershipPage.jsx @@ -1,7 +1,5 @@ -/* eslint-disable react/prop-types */ - import { useState, useContext } from 'react' -import { Navigate } from 'react-router-dom' +import { Navigate, useParams } from 'react-router-dom' import { useMutation, useQuery } from '@apollo/client/react' import styled from 'styled-components' import { useTranslation } from 'react-i18next' @@ -67,12 +65,12 @@ const StyledFormInput = styled(FormInput)` } ` -const DeclineArticleOwnershipPage = ({ match }) => { +const DeclineArticleOwnershipPage = () => { const [isFormSubmitted, setIsFormSubmitted] = useState(false) const [errorMessage, setErrorMessage] = useState(null) const config = useContext(ConfigContext) - const { invitationId } = match.params + const { invitationId } = useParams() const { data, loading } = useQuery(GET_INVITATION_STATUS, { variables: { id: invitationId }, diff --git a/packages/client/app/components/component-frontpage/src/GroupPage.jsx b/packages/client/app/components/component-frontpage/src/GroupPage.jsx index 0fbbb88ed..d39ba2351 100644 --- a/packages/client/app/components/component-frontpage/src/GroupPage.jsx +++ b/packages/client/app/components/component-frontpage/src/GroupPage.jsx @@ -1,7 +1,7 @@ /* stylelint-disable alpha-value-notation, color-function-notation */ import { useState } from 'react' -import { useNavigate } from 'react-router-dom' +import { useNavigate, Navigate } from 'react-router-dom' import { useQuery } from '@apollo/client/react' import { th, grid } from '@coko/client' import styled from 'styled-components' @@ -61,7 +61,7 @@ const GroupPage = () => { ) if (data?.groups.length === 1) { - navigate(`/${data?.groups[0]?.name}`) + return } const redirectToLogin = value => { diff --git a/packages/client/app/components/component-login/src/Login.jsx b/packages/client/app/components/component-login/src/Login.jsx index f021d5ea3..5882199e7 100644 --- a/packages/client/app/components/component-login/src/Login.jsx +++ b/packages/client/app/components/component-login/src/Login.jsx @@ -127,6 +127,10 @@ const Login = () => { ? getQueryStringByName('redirectUrl') : redirectLink + if (localStorage.getItem('token')) { + return + } + if (token) { window.localStorage.setItem('token', token) const intendedPage = localStorage.getItem('intendedPage') @@ -140,9 +144,12 @@ const Login = () => { } const nextpage = `${serverUrl}/auth/orcid?group_id=${config?.groupId}` - return redirectLink ? ( - - ) : ( + + if (redirectLink) { + return + } + + return ( diff --git a/packages/client/app/components/component-published-artifact/components/ArticleArtifactPage.jsx b/packages/client/app/components/component-published-artifact/components/ArticleArtifactPage.jsx index 1723751d8..cab485631 100644 --- a/packages/client/app/components/component-published-artifact/components/ArticleArtifactPage.jsx +++ b/packages/client/app/components/component-published-artifact/components/ArticleArtifactPage.jsx @@ -1,4 +1,5 @@ import { useQuery } from '@apollo/client/react' +import { useParams } from 'react-router-dom' import PropTypes from 'prop-types' import { sanitize } from 'isomorphic-dompurify' import styled from 'styled-components' @@ -39,9 +40,11 @@ const DetailText = styled.div` line-height: ${th('lineHeightBaseSmall')}; ` -const ArticleArtifactPage = ({ match }) => { +const ArticleArtifactPage = () => { + const { version, artifactId } = useParams() + const { loading, data, error } = useQuery(PUBLISHED_MANUSCRIPT_AND_FORMS, { - variables: { id: match.params.version }, + variables: { id: version }, fetchPolicy: 'network-only', }) @@ -52,10 +55,10 @@ const ArticleArtifactPage = ({ match }) => { manuscript.submission = JSON.parse(manuscript.submission) const artifact = manuscript.publishedArtifacts.find( - a => a.id === match.params.artifactId, + a => a.id === artifactId, ) || { title: 'Not found!', - content: `

No published artifact was found with ID ${match.params.artifactId}. Please check the page address.

`, + content: `

No published artifact was found with ID ${artifactId}. Please check the page address.

`, } const relatedDocumentTitle = diff --git a/packages/client/app/pages/GroupWrapper.page.tsx b/packages/client/app/pages/GroupWrapper.page.tsx new file mode 100644 index 000000000..ca76abe23 --- /dev/null +++ b/packages/client/app/pages/GroupWrapper.page.tsx @@ -0,0 +1,38 @@ +import { type ReactNode } from 'react' +import { useParams, Outlet } from 'react-router-dom' +import { useQuery } from '@apollo/client/react' + +import { GET_GROUPS } from '../queries' + +const GroupWrapper = (): ReactNode => { + const { groupName } = useParams() + + /** + * TO DO + * The get group query fetches a lot of data for all groups in the cache. + * Fetch something more minimal to grab the names(same goes for the login + * dropdown) and get the full single group afterwards. + */ + + const { loading, error, data } = useQuery(GET_GROUPS) + + // TO DO - show spinner + if (loading) return null + + if (error) { + // TO DO - show nicer message + return `Something went wrong` + } + + // @ts-ignore + const currentGroup = data.groups.find(group => group.name === groupName) + + if (!currentGroup) { + // TO DO - show nicer message + return `No group named ${groupName}` + } + + return +} + +export default GroupWrapper diff --git a/packages/client/app/pages/index.ts b/packages/client/app/pages/index.ts new file mode 100644 index 000000000..e1d7e06e1 --- /dev/null +++ b/packages/client/app/pages/index.ts @@ -0,0 +1 @@ +export { default as GroupWrapperPage } from './GroupWrapper.page' From f1dd3aca9c0a0a833b10f22d67921259d1f551ac Mon Sep 17 00:00:00 2001 From: yannis Date: Thu, 11 Jun 2026 15:15:17 +0300 Subject: [PATCH 02/16] refactor(ui): move layout to ui and add storybook --- packages/client/.storybook/main.ts | 8 + packages/client/.storybook/preview.ts | 13 + packages/client/app/components/AdminPage.jsx | 24 +- packages/client/app/ui/base/Layout.tsx | 39 + packages/client/package.json | 5 +- .../client/stories/base/Layout.stories.tsx | 41 + .../Control-panel/ControlPanel.stories.jsx | 0 .../MenuItem.stories.jsx | 0 .../chat-collapse/Chat.stories.jsx | 0 .../chat-collapse/CollapseWrapper.stories.jsx | 0 .../chat-collapse/ManuScriptRow.stories.jsx | 0 .../chat-collapse/Menu.stories.jsx | 0 .../common/fixtures.js | 0 .../common/utils.jsx | 0 .../ConfigManagerForm.stories.jsx | 0 .../dashboard/DashboardLayout.stories.jsx | 0 .../dashboard/EditorTable.stories.jsx | 0 .../dashboard/OwnerTable.stories.jsx | 0 .../dashboard/ReviewerTable.stories.jsx | 0 .../ThreadedDiscussion.stories.jsx | 0 .../jats/HTMLtoJATS.stories.jsx | 0 .../reporting/CardCollection.stories.jsx | 0 .../ConcentricStepsChart.stories.jsx | 0 .../reporting/DateRangePicker.stories.jsx | 0 .../reporting/DurationsChart.stories.jsx | 0 .../reporting/Report.stories.jsx | 0 .../reporting/SparkBar.stories.jsx | 0 .../reporting/Table.stories.jsx | 0 .../reporting/TableRow.stories.jsx | 0 .../reporting/mockReportingData.js | 0 .../review/ReviewLayout.stories.jsx | 0 .../review/ReviewMetadata.stories.jsx | 0 .../review/ReviewStatusDonut.stories.jsx | 0 .../shared/Accordion.stories.jsx | 0 .../shared/ActionButton.stories.jsx | 0 .../shared/CommsErrorBanner.stories.jsx | 0 .../shared/Modal.stories.jsx | 0 .../shared/RoundIconButton.stories.jsx | 0 .../submit/SubmissionForms.stories.jsx | 0 .../task-manager/Task.stories.jsx | 0 .../task-manager/TaskList.stories.jsx | 0 .../wax/FullWaxEditor.stories.jsx | 0 .../wax/ProductionWaxEditor.stories.jsx | 0 .../wax/SimpleWaxEditor.stories.jsx | 0 packages/client/yarn.lock | 2363 ++++++++++++++++- 45 files changed, 2376 insertions(+), 117 deletions(-) create mode 100644 packages/client/.storybook/main.ts create mode 100644 packages/client/.storybook/preview.ts create mode 100644 packages/client/app/ui/base/Layout.tsx create mode 100644 packages/client/stories/base/Layout.stories.tsx rename packages/client/{stories => stories_backup}/Control-panel/ControlPanel.stories.jsx (100%) rename packages/client/{stories => stories_backup}/MenuItem.stories.jsx (100%) rename packages/client/{stories => stories_backup}/chat-collapse/Chat.stories.jsx (100%) rename packages/client/{stories => stories_backup}/chat-collapse/CollapseWrapper.stories.jsx (100%) rename packages/client/{stories => stories_backup}/chat-collapse/ManuScriptRow.stories.jsx (100%) rename packages/client/{stories => stories_backup}/chat-collapse/Menu.stories.jsx (100%) rename packages/client/{stories => stories_backup}/common/fixtures.js (100%) rename packages/client/{stories => stories_backup}/common/utils.jsx (100%) rename packages/client/{stories => stories_backup}/config-manager/ConfigManagerForm.stories.jsx (100%) rename packages/client/{stories => stories_backup}/dashboard/DashboardLayout.stories.jsx (100%) rename packages/client/{stories => stories_backup}/dashboard/EditorTable.stories.jsx (100%) rename packages/client/{stories => stories_backup}/dashboard/OwnerTable.stories.jsx (100%) rename packages/client/{stories => stories_backup}/dashboard/ReviewerTable.stories.jsx (100%) rename packages/client/{stories => stories_backup}/discussion-field/ThreadedDiscussion.stories.jsx (100%) rename packages/client/{stories => stories_backup}/jats/HTMLtoJATS.stories.jsx (100%) rename packages/client/{stories => stories_backup}/reporting/CardCollection.stories.jsx (100%) rename packages/client/{stories => stories_backup}/reporting/ConcentricStepsChart.stories.jsx (100%) rename packages/client/{stories => stories_backup}/reporting/DateRangePicker.stories.jsx (100%) rename packages/client/{stories => stories_backup}/reporting/DurationsChart.stories.jsx (100%) rename packages/client/{stories => stories_backup}/reporting/Report.stories.jsx (100%) rename packages/client/{stories => stories_backup}/reporting/SparkBar.stories.jsx (100%) rename packages/client/{stories => stories_backup}/reporting/Table.stories.jsx (100%) rename packages/client/{stories => stories_backup}/reporting/TableRow.stories.jsx (100%) rename packages/client/{stories => stories_backup}/reporting/mockReportingData.js (100%) rename packages/client/{stories => stories_backup}/review/ReviewLayout.stories.jsx (100%) rename packages/client/{stories => stories_backup}/review/ReviewMetadata.stories.jsx (100%) rename packages/client/{stories => stories_backup}/review/ReviewStatusDonut.stories.jsx (100%) rename packages/client/{stories => stories_backup}/shared/Accordion.stories.jsx (100%) rename packages/client/{stories => stories_backup}/shared/ActionButton.stories.jsx (100%) rename packages/client/{stories => stories_backup}/shared/CommsErrorBanner.stories.jsx (100%) rename packages/client/{stories => stories_backup}/shared/Modal.stories.jsx (100%) rename packages/client/{stories => stories_backup}/shared/RoundIconButton.stories.jsx (100%) rename packages/client/{stories => stories_backup}/submit/SubmissionForms.stories.jsx (100%) rename packages/client/{stories => stories_backup}/task-manager/Task.stories.jsx (100%) rename packages/client/{stories => stories_backup}/task-manager/TaskList.stories.jsx (100%) rename packages/client/{stories => stories_backup}/wax/FullWaxEditor.stories.jsx (100%) rename packages/client/{stories => stories_backup}/wax/ProductionWaxEditor.stories.jsx (100%) rename packages/client/{stories => stories_backup}/wax/SimpleWaxEditor.stories.jsx (100%) diff --git a/packages/client/.storybook/main.ts b/packages/client/.storybook/main.ts new file mode 100644 index 000000000..10fde5f32 --- /dev/null +++ b/packages/client/.storybook/main.ts @@ -0,0 +1,8 @@ +/* eslint-disable import/no-extraneous-dependencies */ + +import { defineMain } from '@storybook/react-vite/node' + +export default defineMain({ + framework: '@storybook/react-vite', + stories: ['../stories/**/*.stories.tsx'], +}) diff --git a/packages/client/.storybook/preview.ts b/packages/client/.storybook/preview.ts new file mode 100644 index 000000000..6fc8b03fb --- /dev/null +++ b/packages/client/.storybook/preview.ts @@ -0,0 +1,13 @@ +/* eslint-disable import/no-extraneous-dependencies */ + +import { definePreview } from '@storybook/react-vite' +import * as addonActions from '@storybook/addon-actions/preview' +import * as addonBackgrounds from '@storybook/addon-backgrounds/preview' +import * as addonViewport from '@storybook/addon-viewport/preview' + +export default definePreview({ + addons: [addonActions, addonBackgrounds, addonViewport], + initialGlobals: { + viewport: { value: '', isRotated: false }, + }, +}) diff --git a/packages/client/app/components/AdminPage.jsx b/packages/client/app/components/AdminPage.jsx index 448b35f54..c4849935d 100644 --- a/packages/client/app/components/AdminPage.jsx +++ b/packages/client/app/components/AdminPage.jsx @@ -11,13 +11,13 @@ import { Routes, useLocation, } from 'react-router-dom' -import styled from 'styled-components' import i18next from 'i18next' import { useTranslation } from 'react-i18next' import { JournalContext } from './xpub-journal' import { XpubContext } from './xpub-with-context/src' import { ConfigContext } from './config/src' import { getLanguages } from '../i18n' +import Layout from '../ui/base/Layout' import FormBuilderPage from './component-formbuilder/src/components/FormBuilderPage' import ManuscriptPage from './component-manuscript/src/components/ManuscriptPage' @@ -54,24 +54,6 @@ const getParams = ({ routerPath, path }) => { return matchPath(routerPath, path).params } -const Root = styled.div` - display: flex; - height: 100vh; - max-height: 100vh; - ${props => - props.$converting && - ` - button, - a { - pointer-events: none; - } - `}; - overflow: hidden; - position: relative; - width: 100vw; - z-index: 0; -` - // TODO: Redirect if token expires const PrivateRoute = ({ component: Component, @@ -351,7 +333,7 @@ const AdminPage = () => { ) return ( - + { } path="*" /> )} - + ) } diff --git a/packages/client/app/ui/base/Layout.tsx b/packages/client/app/ui/base/Layout.tsx new file mode 100644 index 000000000..c5aebccd7 --- /dev/null +++ b/packages/client/app/ui/base/Layout.tsx @@ -0,0 +1,39 @@ +import { ReactNode } from 'react' +import styled from 'styled-components' + +const StyledLayout = styled.div<{ $converting: boolean }>` + display: flex; + + height: 100vh; + width: 100vw; + + overflow: hidden; + + ${(props): string | false => + props.$converting && + ` + button, + a { + pointer-events: none; + } + `}; + + > *:last-child { + flex-grow: 1; + } +` + +type LayoutProps = { + children: ReactNode + converting: boolean +} + +// TO DO - drop converting and xpub provider + +const Layout = (props: LayoutProps): ReactNode => { + const { converting = false, children } = props + + return {children} +} + +export default Layout diff --git a/packages/client/package.json b/packages/client/package.json index 9ddd71f1c..773408eb4 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -90,7 +90,10 @@ "yjs": "13.5.38" }, "devDependencies": { - "@types/react": "^19.2.14" + "@storybook/addon-essentials": "8.6.14", + "@storybook/react-vite": "^10.4.3", + "@types/react": "^19.2.14", + "storybook": "^10.4.3" }, "packageManager": "yarn@4.9.2" } diff --git a/packages/client/stories/base/Layout.stories.tsx b/packages/client/stories/base/Layout.stories.tsx new file mode 100644 index 000000000..ca7e57fdd --- /dev/null +++ b/packages/client/stories/base/Layout.stories.tsx @@ -0,0 +1,41 @@ +import styled from 'styled-components' + +import preview from '../../.storybook/preview' +import Layout from '../../app/ui/base/Layout' + +const Left = styled.div` + color: white; + background-color: forestgreen; + width: 300px; + + display: flex; + align-items: center; + justify-content: center; +` + +const Right = styled.div` + background-color: silver; + + display: flex; + align-items: center; + justify-content: center; +` + +const meta = preview.meta({ + component: Layout, +}) + +export const Base = meta.story({ + // drop storybook's default padding for this story + parameters: { + layout: 'fullscreen', + }, + render: () => { + return ( + + Sidebar + Main + + ) + }, +}) diff --git a/packages/client/stories/Control-panel/ControlPanel.stories.jsx b/packages/client/stories_backup/Control-panel/ControlPanel.stories.jsx similarity index 100% rename from packages/client/stories/Control-panel/ControlPanel.stories.jsx rename to packages/client/stories_backup/Control-panel/ControlPanel.stories.jsx diff --git a/packages/client/stories/MenuItem.stories.jsx b/packages/client/stories_backup/MenuItem.stories.jsx similarity index 100% rename from packages/client/stories/MenuItem.stories.jsx rename to packages/client/stories_backup/MenuItem.stories.jsx diff --git a/packages/client/stories/chat-collapse/Chat.stories.jsx b/packages/client/stories_backup/chat-collapse/Chat.stories.jsx similarity index 100% rename from packages/client/stories/chat-collapse/Chat.stories.jsx rename to packages/client/stories_backup/chat-collapse/Chat.stories.jsx diff --git a/packages/client/stories/chat-collapse/CollapseWrapper.stories.jsx b/packages/client/stories_backup/chat-collapse/CollapseWrapper.stories.jsx similarity index 100% rename from packages/client/stories/chat-collapse/CollapseWrapper.stories.jsx rename to packages/client/stories_backup/chat-collapse/CollapseWrapper.stories.jsx diff --git a/packages/client/stories/chat-collapse/ManuScriptRow.stories.jsx b/packages/client/stories_backup/chat-collapse/ManuScriptRow.stories.jsx similarity index 100% rename from packages/client/stories/chat-collapse/ManuScriptRow.stories.jsx rename to packages/client/stories_backup/chat-collapse/ManuScriptRow.stories.jsx diff --git a/packages/client/stories/chat-collapse/Menu.stories.jsx b/packages/client/stories_backup/chat-collapse/Menu.stories.jsx similarity index 100% rename from packages/client/stories/chat-collapse/Menu.stories.jsx rename to packages/client/stories_backup/chat-collapse/Menu.stories.jsx diff --git a/packages/client/stories/common/fixtures.js b/packages/client/stories_backup/common/fixtures.js similarity index 100% rename from packages/client/stories/common/fixtures.js rename to packages/client/stories_backup/common/fixtures.js diff --git a/packages/client/stories/common/utils.jsx b/packages/client/stories_backup/common/utils.jsx similarity index 100% rename from packages/client/stories/common/utils.jsx rename to packages/client/stories_backup/common/utils.jsx diff --git a/packages/client/stories/config-manager/ConfigManagerForm.stories.jsx b/packages/client/stories_backup/config-manager/ConfigManagerForm.stories.jsx similarity index 100% rename from packages/client/stories/config-manager/ConfigManagerForm.stories.jsx rename to packages/client/stories_backup/config-manager/ConfigManagerForm.stories.jsx diff --git a/packages/client/stories/dashboard/DashboardLayout.stories.jsx b/packages/client/stories_backup/dashboard/DashboardLayout.stories.jsx similarity index 100% rename from packages/client/stories/dashboard/DashboardLayout.stories.jsx rename to packages/client/stories_backup/dashboard/DashboardLayout.stories.jsx diff --git a/packages/client/stories/dashboard/EditorTable.stories.jsx b/packages/client/stories_backup/dashboard/EditorTable.stories.jsx similarity index 100% rename from packages/client/stories/dashboard/EditorTable.stories.jsx rename to packages/client/stories_backup/dashboard/EditorTable.stories.jsx diff --git a/packages/client/stories/dashboard/OwnerTable.stories.jsx b/packages/client/stories_backup/dashboard/OwnerTable.stories.jsx similarity index 100% rename from packages/client/stories/dashboard/OwnerTable.stories.jsx rename to packages/client/stories_backup/dashboard/OwnerTable.stories.jsx diff --git a/packages/client/stories/dashboard/ReviewerTable.stories.jsx b/packages/client/stories_backup/dashboard/ReviewerTable.stories.jsx similarity index 100% rename from packages/client/stories/dashboard/ReviewerTable.stories.jsx rename to packages/client/stories_backup/dashboard/ReviewerTable.stories.jsx diff --git a/packages/client/stories/discussion-field/ThreadedDiscussion.stories.jsx b/packages/client/stories_backup/discussion-field/ThreadedDiscussion.stories.jsx similarity index 100% rename from packages/client/stories/discussion-field/ThreadedDiscussion.stories.jsx rename to packages/client/stories_backup/discussion-field/ThreadedDiscussion.stories.jsx diff --git a/packages/client/stories/jats/HTMLtoJATS.stories.jsx b/packages/client/stories_backup/jats/HTMLtoJATS.stories.jsx similarity index 100% rename from packages/client/stories/jats/HTMLtoJATS.stories.jsx rename to packages/client/stories_backup/jats/HTMLtoJATS.stories.jsx diff --git a/packages/client/stories/reporting/CardCollection.stories.jsx b/packages/client/stories_backup/reporting/CardCollection.stories.jsx similarity index 100% rename from packages/client/stories/reporting/CardCollection.stories.jsx rename to packages/client/stories_backup/reporting/CardCollection.stories.jsx diff --git a/packages/client/stories/reporting/ConcentricStepsChart.stories.jsx b/packages/client/stories_backup/reporting/ConcentricStepsChart.stories.jsx similarity index 100% rename from packages/client/stories/reporting/ConcentricStepsChart.stories.jsx rename to packages/client/stories_backup/reporting/ConcentricStepsChart.stories.jsx diff --git a/packages/client/stories/reporting/DateRangePicker.stories.jsx b/packages/client/stories_backup/reporting/DateRangePicker.stories.jsx similarity index 100% rename from packages/client/stories/reporting/DateRangePicker.stories.jsx rename to packages/client/stories_backup/reporting/DateRangePicker.stories.jsx diff --git a/packages/client/stories/reporting/DurationsChart.stories.jsx b/packages/client/stories_backup/reporting/DurationsChart.stories.jsx similarity index 100% rename from packages/client/stories/reporting/DurationsChart.stories.jsx rename to packages/client/stories_backup/reporting/DurationsChart.stories.jsx diff --git a/packages/client/stories/reporting/Report.stories.jsx b/packages/client/stories_backup/reporting/Report.stories.jsx similarity index 100% rename from packages/client/stories/reporting/Report.stories.jsx rename to packages/client/stories_backup/reporting/Report.stories.jsx diff --git a/packages/client/stories/reporting/SparkBar.stories.jsx b/packages/client/stories_backup/reporting/SparkBar.stories.jsx similarity index 100% rename from packages/client/stories/reporting/SparkBar.stories.jsx rename to packages/client/stories_backup/reporting/SparkBar.stories.jsx diff --git a/packages/client/stories/reporting/Table.stories.jsx b/packages/client/stories_backup/reporting/Table.stories.jsx similarity index 100% rename from packages/client/stories/reporting/Table.stories.jsx rename to packages/client/stories_backup/reporting/Table.stories.jsx diff --git a/packages/client/stories/reporting/TableRow.stories.jsx b/packages/client/stories_backup/reporting/TableRow.stories.jsx similarity index 100% rename from packages/client/stories/reporting/TableRow.stories.jsx rename to packages/client/stories_backup/reporting/TableRow.stories.jsx diff --git a/packages/client/stories/reporting/mockReportingData.js b/packages/client/stories_backup/reporting/mockReportingData.js similarity index 100% rename from packages/client/stories/reporting/mockReportingData.js rename to packages/client/stories_backup/reporting/mockReportingData.js diff --git a/packages/client/stories/review/ReviewLayout.stories.jsx b/packages/client/stories_backup/review/ReviewLayout.stories.jsx similarity index 100% rename from packages/client/stories/review/ReviewLayout.stories.jsx rename to packages/client/stories_backup/review/ReviewLayout.stories.jsx diff --git a/packages/client/stories/review/ReviewMetadata.stories.jsx b/packages/client/stories_backup/review/ReviewMetadata.stories.jsx similarity index 100% rename from packages/client/stories/review/ReviewMetadata.stories.jsx rename to packages/client/stories_backup/review/ReviewMetadata.stories.jsx diff --git a/packages/client/stories/review/ReviewStatusDonut.stories.jsx b/packages/client/stories_backup/review/ReviewStatusDonut.stories.jsx similarity index 100% rename from packages/client/stories/review/ReviewStatusDonut.stories.jsx rename to packages/client/stories_backup/review/ReviewStatusDonut.stories.jsx diff --git a/packages/client/stories/shared/Accordion.stories.jsx b/packages/client/stories_backup/shared/Accordion.stories.jsx similarity index 100% rename from packages/client/stories/shared/Accordion.stories.jsx rename to packages/client/stories_backup/shared/Accordion.stories.jsx diff --git a/packages/client/stories/shared/ActionButton.stories.jsx b/packages/client/stories_backup/shared/ActionButton.stories.jsx similarity index 100% rename from packages/client/stories/shared/ActionButton.stories.jsx rename to packages/client/stories_backup/shared/ActionButton.stories.jsx diff --git a/packages/client/stories/shared/CommsErrorBanner.stories.jsx b/packages/client/stories_backup/shared/CommsErrorBanner.stories.jsx similarity index 100% rename from packages/client/stories/shared/CommsErrorBanner.stories.jsx rename to packages/client/stories_backup/shared/CommsErrorBanner.stories.jsx diff --git a/packages/client/stories/shared/Modal.stories.jsx b/packages/client/stories_backup/shared/Modal.stories.jsx similarity index 100% rename from packages/client/stories/shared/Modal.stories.jsx rename to packages/client/stories_backup/shared/Modal.stories.jsx diff --git a/packages/client/stories/shared/RoundIconButton.stories.jsx b/packages/client/stories_backup/shared/RoundIconButton.stories.jsx similarity index 100% rename from packages/client/stories/shared/RoundIconButton.stories.jsx rename to packages/client/stories_backup/shared/RoundIconButton.stories.jsx diff --git a/packages/client/stories/submit/SubmissionForms.stories.jsx b/packages/client/stories_backup/submit/SubmissionForms.stories.jsx similarity index 100% rename from packages/client/stories/submit/SubmissionForms.stories.jsx rename to packages/client/stories_backup/submit/SubmissionForms.stories.jsx diff --git a/packages/client/stories/task-manager/Task.stories.jsx b/packages/client/stories_backup/task-manager/Task.stories.jsx similarity index 100% rename from packages/client/stories/task-manager/Task.stories.jsx rename to packages/client/stories_backup/task-manager/Task.stories.jsx diff --git a/packages/client/stories/task-manager/TaskList.stories.jsx b/packages/client/stories_backup/task-manager/TaskList.stories.jsx similarity index 100% rename from packages/client/stories/task-manager/TaskList.stories.jsx rename to packages/client/stories_backup/task-manager/TaskList.stories.jsx diff --git a/packages/client/stories/wax/FullWaxEditor.stories.jsx b/packages/client/stories_backup/wax/FullWaxEditor.stories.jsx similarity index 100% rename from packages/client/stories/wax/FullWaxEditor.stories.jsx rename to packages/client/stories_backup/wax/FullWaxEditor.stories.jsx diff --git a/packages/client/stories/wax/ProductionWaxEditor.stories.jsx b/packages/client/stories_backup/wax/ProductionWaxEditor.stories.jsx similarity index 100% rename from packages/client/stories/wax/ProductionWaxEditor.stories.jsx rename to packages/client/stories_backup/wax/ProductionWaxEditor.stories.jsx diff --git a/packages/client/stories/wax/SimpleWaxEditor.stories.jsx b/packages/client/stories_backup/wax/SimpleWaxEditor.stories.jsx similarity index 100% rename from packages/client/stories/wax/SimpleWaxEditor.stories.jsx rename to packages/client/stories_backup/wax/SimpleWaxEditor.stories.jsx diff --git a/packages/client/yarn.lock b/packages/client/yarn.lock index f694053df..7aecf737e 100644 --- a/packages/client/yarn.lock +++ b/packages/client/yarn.lock @@ -5,6 +5,13 @@ __metadata: version: 8 cacheKey: 10c0 +"@adobe/css-tools@npm:^4.4.0": + version: 4.5.0 + resolution: "@adobe/css-tools@npm:4.5.0" + checksum: 10c0/fc969e1117098eb4cccdb73beb2508daa0e52760af1183d6288bafea59204943490ab3ede28593032ffb8929c0cee270b2a53254fe61139ab00604ea8fc33cea + languageName: node + linkType: hard + "@ant-design/colors@npm:^8.0.1": version: 8.0.1 resolution: "@ant-design/colors@npm:8.0.1" @@ -131,6 +138,47 @@ __metadata: languageName: node linkType: hard +"@babel/code-frame@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/code-frame@npm:7.29.7" + dependencies: + "@babel/helper-validator-identifier": "npm:^7.29.7" + js-tokens: "npm:^4.0.0" + picocolors: "npm:^1.1.1" + checksum: 10c0/169fc2080169a40c1760155eaaaf739bcb882df0bec76a83adbda5493645bc17270a3434b8848c494b1933e96fe1d147370001e3cda09a39f43ae30f08ef2069 + languageName: node + linkType: hard + +"@babel/compat-data@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/compat-data@npm:7.29.7" + checksum: 10c0/47913f05e08a45a1c9df38c02b4b49e391005085b489432647a1abe112e5d9c75e3be8ea5972b7f6da4ec5d1339922ceb9ea02b8a25d4ed1cb8636e5261f344e + languageName: node + linkType: hard + +"@babel/core@npm:^7.28.0": + version: 7.29.7 + resolution: "@babel/core@npm:7.29.7" + dependencies: + "@babel/code-frame": "npm:^7.29.7" + "@babel/generator": "npm:^7.29.7" + "@babel/helper-compilation-targets": "npm:^7.29.7" + "@babel/helper-module-transforms": "npm:^7.29.7" + "@babel/helpers": "npm:^7.29.7" + "@babel/parser": "npm:^7.29.7" + "@babel/template": "npm:^7.29.7" + "@babel/traverse": "npm:^7.29.7" + "@babel/types": "npm:^7.29.7" + "@jridgewell/remapping": "npm:^2.3.5" + convert-source-map: "npm:^2.0.0" + debug: "npm:^4.1.0" + gensync: "npm:^1.0.0-beta.2" + json5: "npm:^2.2.3" + semver: "npm:^6.3.1" + checksum: 10c0/112fb09c24de7a1de64d1de2c31fe65c4e6af4cb2fb6e6d99ea5373e6fc51e75b88581c0efae4c4c68f119a02a988c7106e95011a41530a2fb8ed793c7eaa07b + languageName: node + linkType: hard + "@babel/generator@npm:^7.25.0": version: 7.25.0 resolution: "@babel/generator@npm:7.25.0" @@ -143,6 +191,39 @@ __metadata: languageName: node linkType: hard +"@babel/generator@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/generator@npm:7.29.7" + dependencies: + "@babel/parser": "npm:^7.29.7" + "@babel/types": "npm:^7.29.7" + "@jridgewell/gen-mapping": "npm:^0.3.12" + "@jridgewell/trace-mapping": "npm:^0.3.28" + jsesc: "npm:^3.0.2" + checksum: 10c0/9bf72b01b5bd0ea5b1288a0e37dbd360bff2f2b1ce73342c0d40fb3db2ec3dc004ada5ffa925c5e12939a416eed59e600d562b8ecd938ce0d27dfd0eb6c6c2b7 + languageName: node + linkType: hard + +"@babel/helper-compilation-targets@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-compilation-targets@npm:7.29.7" + dependencies: + "@babel/compat-data": "npm:^7.29.7" + "@babel/helper-validator-option": "npm:^7.29.7" + browserslist: "npm:^4.24.0" + lru-cache: "npm:^5.1.1" + semver: "npm:^6.3.1" + checksum: 10c0/4c15fd4c69a0a7047799a28a88460c19cede0a0ee8af994ea169114986f4af48b92c7393a4a3fee0456c11a656eece3448a6ed06354453d6c27cccf17195453b + languageName: node + linkType: hard + +"@babel/helper-globals@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-globals@npm:7.29.7" + checksum: 10c0/f38417c40b1129a1b2b519ca961b9040c8827d1444fd74068702286b91b77089431dc76b6b9d5c1496e5da2a4f3ad329c6946e688ba3fa0d1d0b3d2b4f34f36a + languageName: node + linkType: hard + "@babel/helper-module-imports@npm:^7.16.7": version: 7.24.7 resolution: "@babel/helper-module-imports@npm:7.24.7" @@ -153,6 +234,29 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-imports@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-module-imports@npm:7.29.7" + dependencies: + "@babel/traverse": "npm:^7.29.7" + "@babel/types": "npm:^7.29.7" + checksum: 10c0/6adf60d97356027413342a092f818d9678c4f5caff716a33e3284b5ae14e47a9e88059d421dde4ee4894691260039a12602c0e7becadc175602194b40dfa345d + languageName: node + linkType: hard + +"@babel/helper-module-transforms@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-module-transforms@npm:7.29.7" + dependencies: + "@babel/helper-module-imports": "npm:^7.29.7" + "@babel/helper-validator-identifier": "npm:^7.29.7" + "@babel/traverse": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/ee5a2172c24a42be696836f4b0d947489c9729d8adf5821885cf77d1ad5333e3c447368e9a71f67df1099570490553dccf9f888ef0a92a48aa63cb086bd8c7e1 + languageName: node + linkType: hard + "@babel/helper-string-parser@npm:^7.24.8": version: 7.24.8 resolution: "@babel/helper-string-parser@npm:7.24.8" @@ -160,6 +264,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-string-parser@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-string-parser@npm:7.29.7" + checksum: 10c0/194bc0f1716e396d5ffde56ad6119745fb9557662c98611590e5e454906783a4ccb21ce93056b8eb69a4909044834e45d96e50ac695bbe9e3221648fe033c06c + languageName: node + linkType: hard + "@babel/helper-validator-identifier@npm:^7.24.7": version: 7.24.7 resolution: "@babel/helper-validator-identifier@npm:7.24.7" @@ -167,6 +278,30 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-identifier@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-validator-identifier@npm:7.29.7" + checksum: 10c0/4795354e7ae0dcafa72de1cd04ec51252dc1498517170beaf019e03effc5b7bf13c6b21a3949a77e07b8125be7f106ed1131350d8ebd4566ae874094a726d62b + languageName: node + linkType: hard + +"@babel/helper-validator-option@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-validator-option@npm:7.29.7" + checksum: 10c0/d2a06c6d0ac40ba4a2f219fc2cab249c7a94bacdb2686273b7f9598571c908809b48468ff588915a346e6cc7296f60b581023d1d498b747fed06f779d335c2cc + languageName: node + linkType: hard + +"@babel/helpers@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helpers@npm:7.29.7" + dependencies: + "@babel/template": "npm:^7.29.7" + "@babel/types": "npm:^7.29.7" + checksum: 10c0/218e8d10953647c9f44775f5a022b227a182674853b5ea8631889deb7e1a3e4bc870388aaecf59bb8bd92a87f9a96220ed3f70a35bffec6bcf9169ecb67891ac + languageName: node + linkType: hard + "@babel/highlight@npm:^7.24.7": version: 7.24.7 resolution: "@babel/highlight@npm:7.24.7" @@ -179,6 +314,17 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/parser@npm:7.29.7" + dependencies: + "@babel/types": "npm:^7.29.7" + bin: + parser: ./bin/babel-parser.js + checksum: 10c0/65133038f80b54a714d6027cb77cee3f9a6b5c4c6842ce674301e13947cbcbfa8055e63acaf1b84c085d34226a14425b2c2b97b829e0e226d2e8f1299942a51d + languageName: node + linkType: hard + "@babel/parser@npm:^7.25.0, @babel/parser@npm:^7.25.3": version: 7.25.3 resolution: "@babel/parser@npm:7.25.3" @@ -208,6 +354,13 @@ __metadata: languageName: node linkType: hard +"@babel/runtime@npm:^7.17.8": + version: 7.29.7 + resolution: "@babel/runtime@npm:7.29.7" + checksum: 10c0/ca11572f7146b21e0bde6a9ed4bb6a89eafbee5f0944c7eb54d0d8a2dac962c33638a1d611e14faa71dfbb92b4b5f9236232208568a6b7d5c6f3f39ddb91771e + languageName: node + linkType: hard + "@babel/runtime@npm:^7.28.4": version: 7.29.2 resolution: "@babel/runtime@npm:7.29.2" @@ -226,6 +379,17 @@ __metadata: languageName: node linkType: hard +"@babel/template@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/template@npm:7.29.7" + dependencies: + "@babel/code-frame": "npm:^7.29.7" + "@babel/parser": "npm:^7.29.7" + "@babel/types": "npm:^7.29.7" + checksum: 10c0/8bb7f900dcab0e9e1c5ffbc33ca10e0d26b7b2e2ca804becb73ee771b9c4ed6e2908a4ae4a14c08560febb45d2b6b9a173955e42ad404d05f8b04840a14d9c58 + languageName: node + linkType: hard + "@babel/traverse@npm:^7.24.7": version: 7.25.3 resolution: "@babel/traverse@npm:7.25.3" @@ -241,6 +405,31 @@ __metadata: languageName: node linkType: hard +"@babel/traverse@npm:^7.28.0, @babel/traverse@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/traverse@npm:7.29.7" + dependencies: + "@babel/code-frame": "npm:^7.29.7" + "@babel/generator": "npm:^7.29.7" + "@babel/helper-globals": "npm:^7.29.7" + "@babel/parser": "npm:^7.29.7" + "@babel/template": "npm:^7.29.7" + "@babel/types": "npm:^7.29.7" + debug: "npm:^4.3.1" + checksum: 10c0/e256a1fbdb956555b76f3c285b1e453f6bedec8b3afb61751d99d933efd11c7d79caf5ddf2493570058a9f7deaa1b48324380d7c1aa1443fd9508becbf56331a + languageName: node + linkType: hard + +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.28.2, @babel/types@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/types@npm:7.29.7" + dependencies: + "@babel/helper-string-parser": "npm:^7.29.7" + "@babel/helper-validator-identifier": "npm:^7.29.7" + checksum: 10c0/b6623994c69717fa27294f5fa46d59140338e2d86c6c1c13085c84ef7d53086ee357fbf4fe9abe3dd3da75734dc77c4c0df2f90fb29e667558bb3b3fb705e88f + languageName: node + linkType: hard + "@babel/types@npm:^7.24.7, @babel/types@npm:^7.25.0, @babel/types@npm:^7.25.2": version: 7.25.2 resolution: "@babel/types@npm:7.25.2" @@ -499,6 +688,16 @@ __metadata: languageName: node linkType: hard +"@emnapi/core@npm:1.9.2": + version: 1.9.2 + resolution: "@emnapi/core@npm:1.9.2" + dependencies: + "@emnapi/wasi-threads": "npm:1.2.1" + tslib: "npm:^2.4.0" + checksum: 10c0/5500393f953951bad0768fafaa9191f2d938956b20c6d6a79e5ab696a613a25ce6ad23422bc18e86e6ce8deb147619d8d0d7d413a69f84adc01a6633cc353cd9 + languageName: node + linkType: hard + "@emnapi/runtime@npm:1.10.0": version: 1.10.0 resolution: "@emnapi/runtime@npm:1.10.0" @@ -508,6 +707,15 @@ __metadata: languageName: node linkType: hard +"@emnapi/runtime@npm:1.9.2": + version: 1.9.2 + resolution: "@emnapi/runtime@npm:1.9.2" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/61c3a59e0c36784558b8d58eb02bd04815aa5fb0dbfbaf84d1b3050a78aa0cc63ea129ae806bd1e48062bfeb7fc36eb0e5431740d62f64ea51bdf426404b8caa + languageName: node + linkType: hard + "@emnapi/wasi-threads@npm:1.2.1": version: 1.2.1 resolution: "@emnapi/wasi-threads@npm:1.2.1" @@ -657,6 +865,188 @@ __metadata: languageName: node linkType: hard +"@esbuild/aix-ppc64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/aix-ppc64@npm:0.27.7" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/android-arm64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/android-arm64@npm:0.27.7" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/android-arm@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/android-arm@npm:0.27.7" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@esbuild/android-x64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/android-x64@npm:0.27.7" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/darwin-arm64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/darwin-arm64@npm:0.27.7" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/darwin-x64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/darwin-x64@npm:0.27.7" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/freebsd-arm64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/freebsd-arm64@npm:0.27.7" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/freebsd-x64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/freebsd-x64@npm:0.27.7" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/linux-arm64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/linux-arm64@npm:0.27.7" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/linux-arm@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/linux-arm@npm:0.27.7" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@esbuild/linux-ia32@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/linux-ia32@npm:0.27.7" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/linux-loong64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/linux-loong64@npm:0.27.7" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + +"@esbuild/linux-mips64el@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/linux-mips64el@npm:0.27.7" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + +"@esbuild/linux-ppc64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/linux-ppc64@npm:0.27.7" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/linux-riscv64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/linux-riscv64@npm:0.27.7" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + +"@esbuild/linux-s390x@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/linux-s390x@npm:0.27.7" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + +"@esbuild/linux-x64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/linux-x64@npm:0.27.7" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/netbsd-arm64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/netbsd-arm64@npm:0.27.7" + conditions: os=netbsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/netbsd-x64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/netbsd-x64@npm:0.27.7" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/openbsd-arm64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/openbsd-arm64@npm:0.27.7" + conditions: os=openbsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/openbsd-x64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/openbsd-x64@npm:0.27.7" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/openharmony-arm64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/openharmony-arm64@npm:0.27.7" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/sunos-x64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/sunos-x64@npm:0.27.7" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/win32-arm64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/win32-arm64@npm:0.27.7" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/win32-ia32@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/win32-ia32@npm:0.27.7" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/win32-x64@npm:0.27.7": + version: 0.27.7 + resolution: "@esbuild/win32-x64@npm:0.27.7" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@fontsource/roboto@npm:^4.5.8": version: 4.5.8 resolution: "@fontsource/roboto@npm:4.5.8" @@ -696,6 +1086,32 @@ __metadata: languageName: node linkType: hard +"@joshwooding/vite-plugin-react-docgen-typescript@npm:^0.7.0": + version: 0.7.0 + resolution: "@joshwooding/vite-plugin-react-docgen-typescript@npm:0.7.0" + dependencies: + glob: "npm:^13.0.1" + react-docgen-typescript: "npm:^2.2.2" + peerDependencies: + typescript: ">= 4.3.x" + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/6d1a353e4dd0d9d641beafcf8d5c36805ad7f916ae07b817642033bc85c388f819f92dc94db192117dedfaa5d981ac5ef72911315e3e4bf2fe9e23d8956618e6 + languageName: node + linkType: hard + +"@jridgewell/gen-mapping@npm:^0.3.12": + version: 0.3.13 + resolution: "@jridgewell/gen-mapping@npm:0.3.13" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.5.0" + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 10c0/9a7d65fb13bd9aec1fbab74cda08496839b7e2ceb31f5ab922b323e94d7c481ce0fc4fd7e12e2610915ed8af51178bdc61e168e92a8c8b8303b030b03489b13b + languageName: node + linkType: hard + "@jridgewell/gen-mapping@npm:^0.3.5": version: 0.3.5 resolution: "@jridgewell/gen-mapping@npm:0.3.5" @@ -707,6 +1123,16 @@ __metadata: languageName: node linkType: hard +"@jridgewell/remapping@npm:^2.3.5": + version: 2.3.5 + resolution: "@jridgewell/remapping@npm:2.3.5" + dependencies: + "@jridgewell/gen-mapping": "npm:^0.3.5" + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 10c0/3de494219ffeb2c5c38711d0d7bb128097edf91893090a2dbc8ee0b55d092bb7347b1fd0f478486c5eab010e855c73927b1666f2107516d472d24a73017d1194 + languageName: node + linkType: hard + "@jridgewell/resolve-uri@npm:^3.1.0": version: 3.1.2 resolution: "@jridgewell/resolve-uri@npm:3.1.2" @@ -721,130 +1147,440 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14": - version: 1.5.0 - resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" - checksum: 10c0/2eb864f276eb1096c3c11da3e9bb518f6d9fc0023c78344cdc037abadc725172c70314bdb360f2d4b7bffec7f5d657ce006816bc5d4ecb35e61b66132db00c18 +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14": + version: 1.5.0 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" + checksum: 10c0/2eb864f276eb1096c3c11da3e9bb518f6d9fc0023c78344cdc037abadc725172c70314bdb360f2d4b7bffec7f5d657ce006816bc5d4ecb35e61b66132db00c18 + languageName: node + linkType: hard + +"@jridgewell/sourcemap-codec@npm:^1.5.0, @jridgewell/sourcemap-codec@npm:^1.5.5": + version: 1.5.5 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" + checksum: 10c0/f9e538f302b63c0ebc06eecb1dd9918dd4289ed36147a0ddce35d6ea4d7ebbda243cda7b2213b6a5e1d8087a298d5cf630fb2bd39329cdecb82017023f6081a0 + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": + version: 0.3.25 + resolution: "@jridgewell/trace-mapping@npm:0.3.25" + dependencies: + "@jridgewell/resolve-uri": "npm:^3.1.0" + "@jridgewell/sourcemap-codec": "npm:^1.4.14" + checksum: 10c0/3d1ce6ebc69df9682a5a8896b414c6537e428a1d68b02fcc8363b04284a8ca0df04d0ee3013132252ab14f2527bc13bea6526a912ecb5658f0e39fd2860b4df4 + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:^0.3.28": + version: 0.3.31 + resolution: "@jridgewell/trace-mapping@npm:0.3.31" + dependencies: + "@jridgewell/resolve-uri": "npm:^3.1.0" + "@jridgewell/sourcemap-codec": "npm:^1.4.14" + checksum: 10c0/4b30ec8cd56c5fd9a661f088230af01e0c1a3888d11ffb6b47639700f71225be21d1f7e168048d6d4f9449207b978a235c07c8f15c07705685d16dc06280e9d9 + languageName: node + linkType: hard + +"@lezer/common@npm:^1.0.0, @lezer/common@npm:^1.0.2, @lezer/common@npm:^1.1.0, @lezer/common@npm:^1.2.0": + version: 1.2.1 + resolution: "@lezer/common@npm:1.2.1" + checksum: 10c0/af61436dc026f8deebaded13d8e1beea2ae307cbbfb270116cdedadb8208f0674da9c3b5963128a2b1cd4072b4e90bc8128133f4feaf31b6e801e4568f1a15a6 + languageName: node + linkType: hard + +"@lezer/css@npm:^1.0.0, @lezer/css@npm:^1.1.0": + version: 1.1.8 + resolution: "@lezer/css@npm:1.1.8" + dependencies: + "@lezer/common": "npm:^1.2.0" + "@lezer/highlight": "npm:^1.0.0" + "@lezer/lr": "npm:^1.0.0" + checksum: 10c0/d28a84c912eedd675b437a7d0b95c72a6c00987da7dc208049889f64ce57250e9ae640856d007a32df6b8f4b0c8986e7751b40e2536b4df26382a78ead362281 + languageName: node + linkType: hard + +"@lezer/highlight@npm:^1.0.0, @lezer/highlight@npm:^1.1.3": + version: 1.2.0 + resolution: "@lezer/highlight@npm:1.2.0" + dependencies: + "@lezer/common": "npm:^1.0.0" + checksum: 10c0/d4312f95b78e4b6f10833b1cf99601c6381c22b755bbf60fd61d6fe9b4cf7780650e2e2dadf75beb8d94824dcb5ec81da5cfc9ca54122688a482e488103105aa + languageName: node + linkType: hard + +"@lezer/html@npm:^1.3.0": + version: 1.3.10 + resolution: "@lezer/html@npm:1.3.10" + dependencies: + "@lezer/common": "npm:^1.2.0" + "@lezer/highlight": "npm:^1.0.0" + "@lezer/lr": "npm:^1.0.0" + checksum: 10c0/a7e782f9e9c5c5ffaa4a6fcf4ea5284e62c8fd3f0d378c86738b57077c002cbb013aeeb8aaae292b9517fea8b959216ce7af053269329962f6df2c7f9c2c8d99 + languageName: node + linkType: hard + +"@lezer/javascript@npm:^1.0.0": + version: 1.4.17 + resolution: "@lezer/javascript@npm:1.4.17" + dependencies: + "@lezer/common": "npm:^1.2.0" + "@lezer/highlight": "npm:^1.1.3" + "@lezer/lr": "npm:^1.3.0" + checksum: 10c0/5e69eabd7b6ea58ff828073324282a38567488bd6da1541023f1a66268a0ac9d01cde924f4fad183fcbf630ac33680e6b859a18f6fbec14ffb76073cdccf7b2b + languageName: node + linkType: hard + +"@lezer/json@npm:^1.0.0": + version: 1.0.2 + resolution: "@lezer/json@npm:1.0.2" + dependencies: + "@lezer/common": "npm:^1.2.0" + "@lezer/highlight": "npm:^1.0.0" + "@lezer/lr": "npm:^1.0.0" + checksum: 10c0/a84283b4e4ded682b5e90a068c52155deaeac79e8dc16da0e9904e72633be029a00ad2da26daa259e503ae3b116722985c3e15d9448336e5f0fde59f79b716ad + languageName: node + linkType: hard + +"@lezer/lr@npm:^1.0.0, @lezer/lr@npm:^1.3.0": + version: 1.4.2 + resolution: "@lezer/lr@npm:1.4.2" + dependencies: + "@lezer/common": "npm:^1.0.0" + checksum: 10c0/22bb5d0d4b33d0de5eb0706b7e5b5f2d20f570e112d9110009bd35b62ff10f2eb4eff8da4cf373dd4ddf5e06a304120b8f039add7ed9997c981c13945d5329cd + languageName: node + linkType: hard + +"@mdx-js/react@npm:^3.0.0": + version: 3.1.1 + resolution: "@mdx-js/react@npm:3.1.1" + dependencies: + "@types/mdx": "npm:^2.0.0" + peerDependencies: + "@types/react": ">=16" + react: ">=16" + checksum: 10c0/34ca98bc2a0f969894ea144dc5c8a5294690505458cd24965cd9be854d779c193ad9192bf9143c4c18438fafd1902e100d99067e045c69319288562d497558c6 + languageName: node + linkType: hard + +"@napi-rs/wasm-runtime@npm:^1.1.4": + version: 1.1.4 + resolution: "@napi-rs/wasm-runtime@npm:1.1.4" + dependencies: + "@tybys/wasm-util": "npm:^0.10.1" + peerDependencies: + "@emnapi/core": ^1.7.1 + "@emnapi/runtime": ^1.7.1 + checksum: 10c0/2e88e1955258949ccf2d18c79975821ad38071b465ef126a5e14110977b97868867b016c1ad046e963cccc42c0bd9db6c8ff5fd1ebb61b87bb3487f339041658 + languageName: node + linkType: hard + +"@npmcli/agent@npm:^3.0.0": + version: 3.0.0 + resolution: "@npmcli/agent@npm:3.0.0" + dependencies: + agent-base: "npm:^7.1.0" + http-proxy-agent: "npm:^7.0.0" + https-proxy-agent: "npm:^7.0.1" + lru-cache: "npm:^10.0.1" + socks-proxy-agent: "npm:^8.0.3" + checksum: 10c0/efe37b982f30740ee77696a80c196912c274ecd2cb243bc6ae7053a50c733ce0f6c09fda085145f33ecf453be19654acca74b69e81eaad4c90f00ccffe2f9271 + languageName: node + linkType: hard + +"@npmcli/fs@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/fs@npm:4.0.0" + dependencies: + semver: "npm:^7.3.5" + checksum: 10c0/c90935d5ce670c87b6b14fab04a965a3b8137e585f8b2a6257263bd7f97756dd736cb165bb470e5156a9e718ecd99413dccc54b1138c1a46d6ec7cf325982fe5 + languageName: node + linkType: hard + +"@oxc-parser/binding-android-arm-eabi@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-android-arm-eabi@npm:0.127.0" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@oxc-parser/binding-android-arm64@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-android-arm64@npm:0.127.0" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@oxc-parser/binding-darwin-arm64@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-darwin-arm64@npm:0.127.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@oxc-parser/binding-darwin-x64@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-darwin-x64@npm:0.127.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@oxc-parser/binding-freebsd-x64@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-freebsd-x64@npm:0.127.0" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@oxc-parser/binding-linux-arm-gnueabihf@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-linux-arm-gnueabihf@npm:0.127.0" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@oxc-parser/binding-linux-arm-musleabihf@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-linux-arm-musleabihf@npm:0.127.0" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@oxc-parser/binding-linux-arm64-gnu@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-linux-arm64-gnu@npm:0.127.0" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@oxc-parser/binding-linux-arm64-musl@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-linux-arm64-musl@npm:0.127.0" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@oxc-parser/binding-linux-ppc64-gnu@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-linux-ppc64-gnu@npm:0.127.0" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@oxc-parser/binding-linux-riscv64-gnu@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-linux-riscv64-gnu@npm:0.127.0" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@oxc-parser/binding-linux-riscv64-musl@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-linux-riscv64-musl@npm:0.127.0" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@oxc-parser/binding-linux-s390x-gnu@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-linux-s390x-gnu@npm:0.127.0" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@oxc-parser/binding-linux-x64-gnu@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-linux-x64-gnu@npm:0.127.0" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@oxc-parser/binding-linux-x64-musl@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-linux-x64-musl@npm:0.127.0" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@oxc-parser/binding-openharmony-arm64@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-openharmony-arm64@npm:0.127.0" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + +"@oxc-parser/binding-wasm32-wasi@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-wasm32-wasi@npm:0.127.0" + dependencies: + "@emnapi/core": "npm:1.9.2" + "@emnapi/runtime": "npm:1.9.2" + "@napi-rs/wasm-runtime": "npm:^1.1.4" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@oxc-parser/binding-win32-arm64-msvc@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-win32-arm64-msvc@npm:0.127.0" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@oxc-parser/binding-win32-ia32-msvc@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-win32-ia32-msvc@npm:0.127.0" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@oxc-parser/binding-win32-x64-msvc@npm:0.127.0": + version: 0.127.0 + resolution: "@oxc-parser/binding-win32-x64-msvc@npm:0.127.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@oxc-project/types@npm:=0.127.0, @oxc-project/types@npm:^0.127.0": + version: 0.127.0 + resolution: "@oxc-project/types@npm:0.127.0" + checksum: 10c0/52c0947ac64a9ca119fe971f947e784a35ecd14a072fa3f542a58a5f6c42010b53f2bf92731e39b9899b83c990a9517bbd29d1e5a5b7b489e52616685c6a9278 + languageName: node + linkType: hard + +"@oxc-resolver/binding-android-arm-eabi@npm:11.20.0": + version: 11.20.0 + resolution: "@oxc-resolver/binding-android-arm-eabi@npm:11.20.0" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@oxc-resolver/binding-android-arm64@npm:11.20.0": + version: 11.20.0 + resolution: "@oxc-resolver/binding-android-arm64@npm:11.20.0" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@oxc-resolver/binding-darwin-arm64@npm:11.20.0": + version: 11.20.0 + resolution: "@oxc-resolver/binding-darwin-arm64@npm:11.20.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@oxc-resolver/binding-darwin-x64@npm:11.20.0": + version: 11.20.0 + resolution: "@oxc-resolver/binding-darwin-x64@npm:11.20.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@oxc-resolver/binding-freebsd-x64@npm:11.20.0": + version: 11.20.0 + resolution: "@oxc-resolver/binding-freebsd-x64@npm:11.20.0" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.20.0": + version: 11.20.0 + resolution: "@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.20.0" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@oxc-resolver/binding-linux-arm-musleabihf@npm:11.20.0": + version: 11.20.0 + resolution: "@oxc-resolver/binding-linux-arm-musleabihf@npm:11.20.0" + conditions: os=linux & cpu=arm languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": - version: 0.3.25 - resolution: "@jridgewell/trace-mapping@npm:0.3.25" - dependencies: - "@jridgewell/resolve-uri": "npm:^3.1.0" - "@jridgewell/sourcemap-codec": "npm:^1.4.14" - checksum: 10c0/3d1ce6ebc69df9682a5a8896b414c6537e428a1d68b02fcc8363b04284a8ca0df04d0ee3013132252ab14f2527bc13bea6526a912ecb5658f0e39fd2860b4df4 +"@oxc-resolver/binding-linux-arm64-gnu@npm:11.20.0": + version: 11.20.0 + resolution: "@oxc-resolver/binding-linux-arm64-gnu@npm:11.20.0" + conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@lezer/common@npm:^1.0.0, @lezer/common@npm:^1.0.2, @lezer/common@npm:^1.1.0, @lezer/common@npm:^1.2.0": - version: 1.2.1 - resolution: "@lezer/common@npm:1.2.1" - checksum: 10c0/af61436dc026f8deebaded13d8e1beea2ae307cbbfb270116cdedadb8208f0674da9c3b5963128a2b1cd4072b4e90bc8128133f4feaf31b6e801e4568f1a15a6 +"@oxc-resolver/binding-linux-arm64-musl@npm:11.20.0": + version: 11.20.0 + resolution: "@oxc-resolver/binding-linux-arm64-musl@npm:11.20.0" + conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@lezer/css@npm:^1.0.0, @lezer/css@npm:^1.1.0": - version: 1.1.8 - resolution: "@lezer/css@npm:1.1.8" - dependencies: - "@lezer/common": "npm:^1.2.0" - "@lezer/highlight": "npm:^1.0.0" - "@lezer/lr": "npm:^1.0.0" - checksum: 10c0/d28a84c912eedd675b437a7d0b95c72a6c00987da7dc208049889f64ce57250e9ae640856d007a32df6b8f4b0c8986e7751b40e2536b4df26382a78ead362281 +"@oxc-resolver/binding-linux-ppc64-gnu@npm:11.20.0": + version: 11.20.0 + resolution: "@oxc-resolver/binding-linux-ppc64-gnu@npm:11.20.0" + conditions: os=linux & cpu=ppc64 & libc=glibc languageName: node linkType: hard -"@lezer/highlight@npm:^1.0.0, @lezer/highlight@npm:^1.1.3": - version: 1.2.0 - resolution: "@lezer/highlight@npm:1.2.0" - dependencies: - "@lezer/common": "npm:^1.0.0" - checksum: 10c0/d4312f95b78e4b6f10833b1cf99601c6381c22b755bbf60fd61d6fe9b4cf7780650e2e2dadf75beb8d94824dcb5ec81da5cfc9ca54122688a482e488103105aa +"@oxc-resolver/binding-linux-riscv64-gnu@npm:11.20.0": + version: 11.20.0 + resolution: "@oxc-resolver/binding-linux-riscv64-gnu@npm:11.20.0" + conditions: os=linux & cpu=riscv64 & libc=glibc languageName: node linkType: hard -"@lezer/html@npm:^1.3.0": - version: 1.3.10 - resolution: "@lezer/html@npm:1.3.10" - dependencies: - "@lezer/common": "npm:^1.2.0" - "@lezer/highlight": "npm:^1.0.0" - "@lezer/lr": "npm:^1.0.0" - checksum: 10c0/a7e782f9e9c5c5ffaa4a6fcf4ea5284e62c8fd3f0d378c86738b57077c002cbb013aeeb8aaae292b9517fea8b959216ce7af053269329962f6df2c7f9c2c8d99 +"@oxc-resolver/binding-linux-riscv64-musl@npm:11.20.0": + version: 11.20.0 + resolution: "@oxc-resolver/binding-linux-riscv64-musl@npm:11.20.0" + conditions: os=linux & cpu=riscv64 & libc=musl languageName: node linkType: hard -"@lezer/javascript@npm:^1.0.0": - version: 1.4.17 - resolution: "@lezer/javascript@npm:1.4.17" - dependencies: - "@lezer/common": "npm:^1.2.0" - "@lezer/highlight": "npm:^1.1.3" - "@lezer/lr": "npm:^1.3.0" - checksum: 10c0/5e69eabd7b6ea58ff828073324282a38567488bd6da1541023f1a66268a0ac9d01cde924f4fad183fcbf630ac33680e6b859a18f6fbec14ffb76073cdccf7b2b +"@oxc-resolver/binding-linux-s390x-gnu@npm:11.20.0": + version: 11.20.0 + resolution: "@oxc-resolver/binding-linux-s390x-gnu@npm:11.20.0" + conditions: os=linux & cpu=s390x & libc=glibc languageName: node linkType: hard -"@lezer/json@npm:^1.0.0": - version: 1.0.2 - resolution: "@lezer/json@npm:1.0.2" - dependencies: - "@lezer/common": "npm:^1.2.0" - "@lezer/highlight": "npm:^1.0.0" - "@lezer/lr": "npm:^1.0.0" - checksum: 10c0/a84283b4e4ded682b5e90a068c52155deaeac79e8dc16da0e9904e72633be029a00ad2da26daa259e503ae3b116722985c3e15d9448336e5f0fde59f79b716ad +"@oxc-resolver/binding-linux-x64-gnu@npm:11.20.0": + version: 11.20.0 + resolution: "@oxc-resolver/binding-linux-x64-gnu@npm:11.20.0" + conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@lezer/lr@npm:^1.0.0, @lezer/lr@npm:^1.3.0": - version: 1.4.2 - resolution: "@lezer/lr@npm:1.4.2" - dependencies: - "@lezer/common": "npm:^1.0.0" - checksum: 10c0/22bb5d0d4b33d0de5eb0706b7e5b5f2d20f570e112d9110009bd35b62ff10f2eb4eff8da4cf373dd4ddf5e06a304120b8f039add7ed9997c981c13945d5329cd +"@oxc-resolver/binding-linux-x64-musl@npm:11.20.0": + version: 11.20.0 + resolution: "@oxc-resolver/binding-linux-x64-musl@npm:11.20.0" + conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@napi-rs/wasm-runtime@npm:^1.1.4": - version: 1.1.4 - resolution: "@napi-rs/wasm-runtime@npm:1.1.4" - dependencies: - "@tybys/wasm-util": "npm:^0.10.1" - peerDependencies: - "@emnapi/core": ^1.7.1 - "@emnapi/runtime": ^1.7.1 - checksum: 10c0/2e88e1955258949ccf2d18c79975821ad38071b465ef126a5e14110977b97868867b016c1ad046e963cccc42c0bd9db6c8ff5fd1ebb61b87bb3487f339041658 +"@oxc-resolver/binding-openharmony-arm64@npm:11.20.0": + version: 11.20.0 + resolution: "@oxc-resolver/binding-openharmony-arm64@npm:11.20.0" + conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard -"@npmcli/agent@npm:^3.0.0": - version: 3.0.0 - resolution: "@npmcli/agent@npm:3.0.0" +"@oxc-resolver/binding-wasm32-wasi@npm:11.20.0": + version: 11.20.0 + resolution: "@oxc-resolver/binding-wasm32-wasi@npm:11.20.0" dependencies: - agent-base: "npm:^7.1.0" - http-proxy-agent: "npm:^7.0.0" - https-proxy-agent: "npm:^7.0.1" - lru-cache: "npm:^10.0.1" - socks-proxy-agent: "npm:^8.0.3" - checksum: 10c0/efe37b982f30740ee77696a80c196912c274ecd2cb243bc6ae7053a50c733ce0f6c09fda085145f33ecf453be19654acca74b69e81eaad4c90f00ccffe2f9271 + "@emnapi/core": "npm:1.10.0" + "@emnapi/runtime": "npm:1.10.0" + "@napi-rs/wasm-runtime": "npm:^1.1.4" + conditions: cpu=wasm32 languageName: node linkType: hard -"@npmcli/fs@npm:^4.0.0": - version: 4.0.0 - resolution: "@npmcli/fs@npm:4.0.0" - dependencies: - semver: "npm:^7.3.5" - checksum: 10c0/c90935d5ce670c87b6b14fab04a965a3b8137e585f8b2a6257263bd7f97756dd736cb165bb470e5156a9e718ecd99413dccc54b1138c1a46d6ec7cf325982fe5 +"@oxc-resolver/binding-win32-arm64-msvc@npm:11.20.0": + version: 11.20.0 + resolution: "@oxc-resolver/binding-win32-arm64-msvc@npm:11.20.0" + conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@oxc-project/types@npm:=0.127.0": - version: 0.127.0 - resolution: "@oxc-project/types@npm:0.127.0" - checksum: 10c0/52c0947ac64a9ca119fe971f947e784a35ecd14a072fa3f542a58a5f6c42010b53f2bf92731e39b9899b83c990a9517bbd29d1e5a5b7b489e52616685c6a9278 +"@oxc-resolver/binding-win32-x64-msvc@npm:11.20.0": + version: 11.20.0 + resolution: "@oxc-resolver/binding-win32-x64-msvc@npm:11.20.0" + conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -1664,6 +2400,22 @@ __metadata: languageName: node linkType: hard +"@rollup/pluginutils@npm:^5.0.2": + version: 5.4.0 + resolution: "@rollup/pluginutils@npm:5.4.0" + dependencies: + "@types/estree": "npm:^1.0.0" + estree-walker: "npm:^2.0.2" + picomatch: "npm:^4.0.2" + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: 10c0/ccc2cbd3a05df642df60ab05ffb81b2e564bd945e2a118bb8a474ea75b941033c8f44273133d4865643cca1492d0c80b14de1281f74779a64285a80fc3a194d8 + languageName: node + linkType: hard + "@sentry-internal/browser-utils@npm:10.50.0": version: 10.50.0 resolution: "@sentry-internal/browser-utils@npm:10.50.0" @@ -1741,10 +2493,337 @@ __metadata: languageName: node linkType: hard -"@standard-schema/utils@npm:^0.3.0": - version: 0.3.0 - resolution: "@standard-schema/utils@npm:0.3.0" - checksum: 10c0/6eb74cd13e52d5fc74054df51e37d947ef53f3ab9e02c085665dcca3c38c60ece8d735cebbdf18fbb13c775fbcb9becb3f53109b0e092a63f0f7389ce0993fd0 +"@standard-schema/utils@npm:^0.3.0": + version: 0.3.0 + resolution: "@standard-schema/utils@npm:0.3.0" + checksum: 10c0/6eb74cd13e52d5fc74054df51e37d947ef53f3ab9e02c085665dcca3c38c60ece8d735cebbdf18fbb13c775fbcb9becb3f53109b0e092a63f0f7389ce0993fd0 + languageName: node + linkType: hard + +"@storybook/addon-actions@npm:8.6.14": + version: 8.6.14 + resolution: "@storybook/addon-actions@npm:8.6.14" + dependencies: + "@storybook/global": "npm:^5.0.0" + "@types/uuid": "npm:^9.0.1" + dequal: "npm:^2.0.2" + polished: "npm:^4.2.2" + uuid: "npm:^9.0.0" + peerDependencies: + storybook: ^8.6.14 + checksum: 10c0/7a5d4faa15dd42f8f98335b6d817e1e2ffb50084001dc430aa3baf5c77edece16f0e866e8ce488e1c7a7a8f85465a6a71421373b87877375beafbe4729ada14a + languageName: node + linkType: hard + +"@storybook/addon-backgrounds@npm:8.6.14": + version: 8.6.14 + resolution: "@storybook/addon-backgrounds@npm:8.6.14" + dependencies: + "@storybook/global": "npm:^5.0.0" + memoizerific: "npm:^1.11.3" + ts-dedent: "npm:^2.0.0" + peerDependencies: + storybook: ^8.6.14 + checksum: 10c0/e42befb774082313e7c0b94676dbbaa6a79dfd65b127dd474966d878fbd94e70a35651d5daccd1e09138775a1d275257279ae1092ddaaa840b7dc21839f0f5b9 + languageName: node + linkType: hard + +"@storybook/addon-controls@npm:8.6.14": + version: 8.6.14 + resolution: "@storybook/addon-controls@npm:8.6.14" + dependencies: + "@storybook/global": "npm:^5.0.0" + dequal: "npm:^2.0.2" + ts-dedent: "npm:^2.0.0" + peerDependencies: + storybook: ^8.6.14 + checksum: 10c0/a02a818be873ee7a630f5ca4a46fe16fc31edec2b16b0988ce4f8bcdd63650aaf1a2cd0356e1b42557e1a1bb2f46de4653e071e7b2b53a60c9a3e60a93fe19ef + languageName: node + linkType: hard + +"@storybook/addon-docs@npm:8.6.14": + version: 8.6.14 + resolution: "@storybook/addon-docs@npm:8.6.14" + dependencies: + "@mdx-js/react": "npm:^3.0.0" + "@storybook/blocks": "npm:8.6.14" + "@storybook/csf-plugin": "npm:8.6.14" + "@storybook/react-dom-shim": "npm:8.6.14" + react: "npm:^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + react-dom: "npm:^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + ts-dedent: "npm:^2.0.0" + peerDependencies: + storybook: ^8.6.14 + checksum: 10c0/1668d40977624e3495b0cd3f009957994db04cec6de39645311e892cc1de99bf5a98bea9e9783d8063627c27b9545d222b1fdc490c23c6fadeead42ce0605fcb + languageName: node + linkType: hard + +"@storybook/addon-essentials@npm:8.6.14": + version: 8.6.14 + resolution: "@storybook/addon-essentials@npm:8.6.14" + dependencies: + "@storybook/addon-actions": "npm:8.6.14" + "@storybook/addon-backgrounds": "npm:8.6.14" + "@storybook/addon-controls": "npm:8.6.14" + "@storybook/addon-docs": "npm:8.6.14" + "@storybook/addon-highlight": "npm:8.6.14" + "@storybook/addon-measure": "npm:8.6.14" + "@storybook/addon-outline": "npm:8.6.14" + "@storybook/addon-toolbars": "npm:8.6.14" + "@storybook/addon-viewport": "npm:8.6.14" + ts-dedent: "npm:^2.0.0" + peerDependencies: + storybook: ^8.6.14 + checksum: 10c0/77235e359d25267f7339e3c4a920329fccf7febbc5b81e13e7fc1f7d429e22385027dfaf30e2639865271c270d810df815a165e11a512735eedebb5c649c5adf + languageName: node + linkType: hard + +"@storybook/addon-highlight@npm:8.6.14": + version: 8.6.14 + resolution: "@storybook/addon-highlight@npm:8.6.14" + dependencies: + "@storybook/global": "npm:^5.0.0" + peerDependencies: + storybook: ^8.6.14 + checksum: 10c0/db04b21cc3dc6185ce0051de08e0402899986d0b4b640ddbf1c8386bea5b1ed54b5a9b7e8a40e02973b73706839bcda1b324daf1eaafb465215247e6f548f817 + languageName: node + linkType: hard + +"@storybook/addon-measure@npm:8.6.14": + version: 8.6.14 + resolution: "@storybook/addon-measure@npm:8.6.14" + dependencies: + "@storybook/global": "npm:^5.0.0" + tiny-invariant: "npm:^1.3.1" + peerDependencies: + storybook: ^8.6.14 + checksum: 10c0/a44f1c23e1665adf01684ce62b9c98e5b460aa96024c3c7be4bf9caa7c1073c4d9470b88bc5f814856594b7b90d9b877d5d58cfdbef2df77d483c1c3694ce37e + languageName: node + linkType: hard + +"@storybook/addon-outline@npm:8.6.14": + version: 8.6.14 + resolution: "@storybook/addon-outline@npm:8.6.14" + dependencies: + "@storybook/global": "npm:^5.0.0" + ts-dedent: "npm:^2.0.0" + peerDependencies: + storybook: ^8.6.14 + checksum: 10c0/b54d71299a75588d7d424fb986433435d69974f4782986b7c4ef7db964bc9f85c75a07d5b0a2a0eec5b018284ddd4d4851e14fb4e131f41a6463fc16db234617 + languageName: node + linkType: hard + +"@storybook/addon-toolbars@npm:8.6.14": + version: 8.6.14 + resolution: "@storybook/addon-toolbars@npm:8.6.14" + peerDependencies: + storybook: ^8.6.14 + checksum: 10c0/3fb0fe13fab65be101abda613c1c92e08c2aa0cba97ff2e37aa410af5fe2c1ebc15203627039c265e9667af294ea0cd7bb6e7bd84cb854bad5d0245a9ce66b79 + languageName: node + linkType: hard + +"@storybook/addon-viewport@npm:8.6.14": + version: 8.6.14 + resolution: "@storybook/addon-viewport@npm:8.6.14" + dependencies: + memoizerific: "npm:^1.11.3" + peerDependencies: + storybook: ^8.6.14 + checksum: 10c0/00a353ce87c79a7b08fd78cab87045c5d29996ea3fcd2a4072380e0f76a6e0bfc9385f743b98764aaff0740e8460b9d2a37864a1d0e91bf48f26e3d5a1984e51 + languageName: node + linkType: hard + +"@storybook/blocks@npm:8.6.14": + version: 8.6.14 + resolution: "@storybook/blocks@npm:8.6.14" + dependencies: + "@storybook/icons": "npm:^1.2.12" + ts-dedent: "npm:^2.0.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + storybook: ^8.6.14 + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + checksum: 10c0/3f87c1f224031dee8b5fa6e296022997d21956832fea1e4ffa3525931c05a8ef6450b67c728635297a08548d65ef5abde05d7740d4ea3a9a811f2ff08a5f0148 + languageName: node + linkType: hard + +"@storybook/builder-vite@npm:10.4.3": + version: 10.4.3 + resolution: "@storybook/builder-vite@npm:10.4.3" + dependencies: + "@storybook/csf-plugin": "npm:10.4.3" + ts-dedent: "npm:^2.0.0" + peerDependencies: + storybook: ^10.4.3 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: 10c0/e29d8cd3e1d68b49b9fe674e0c2a4216569908a9e2ec2a0c9522f124efa69c7d9f649e7f74dcb05d2c2eb6ff85bb36dc80720518bc382b695837ec83198dfbf1 + languageName: node + linkType: hard + +"@storybook/csf-plugin@npm:10.4.3": + version: 10.4.3 + resolution: "@storybook/csf-plugin@npm:10.4.3" + dependencies: + unplugin: "npm:^2.3.5" + peerDependencies: + esbuild: "*" + rollup: "*" + storybook: ^10.4.3 + vite: "*" + webpack: "*" + peerDependenciesMeta: + esbuild: + optional: true + rollup: + optional: true + vite: + optional: true + webpack: + optional: true + checksum: 10c0/b5fcf3ccd8431967e0d8cac98692997571f364c6070205eddf8e91e06991681af8c1ad39acde94e8ed8cad78b65f5da510eb5eefa7463eaa85164c3b27f1ff8a + languageName: node + linkType: hard + +"@storybook/csf-plugin@npm:8.6.14": + version: 8.6.14 + resolution: "@storybook/csf-plugin@npm:8.6.14" + dependencies: + unplugin: "npm:^1.3.1" + peerDependencies: + storybook: ^8.6.14 + checksum: 10c0/3f2cebd6046aea554d2e740c4d262005c580018dfcbcca8d9a589f9e893d407da405ace235595b3e110fb6ed21b840ff1645508a98764017ca5d1d4c56027172 + languageName: node + linkType: hard + +"@storybook/global@npm:^5.0.0": + version: 5.0.0 + resolution: "@storybook/global@npm:5.0.0" + checksum: 10c0/8f1b61dcdd3a89584540896e659af2ecc700bc740c16909a7be24ac19127ea213324de144a141f7caf8affaed017d064fea0618d453afbe027cf60f54b4a6d0b + languageName: node + linkType: hard + +"@storybook/icons@npm:^1.2.12": + version: 1.6.0 + resolution: "@storybook/icons@npm:1.6.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + checksum: 10c0/bbec9201a78a730195f9cf377b15856dc414a54d04e30d16c379d062425cc617bfd0d6586ba1716012cfbdab461f0c9693a6a52920f9bd09c7b4291fb116f59c + languageName: node + linkType: hard + +"@storybook/icons@npm:^2.0.2": + version: 2.0.2 + resolution: "@storybook/icons@npm:2.0.2" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + checksum: 10c0/072486356fc929ba5a1a225a8636f0e50b2019083e86e4d48d55aeeae4b40f17731cd1eea9cf1785c53e5fc4409fa93aeca15dccb96675c8e7ab536b18ba864c + languageName: node + linkType: hard + +"@storybook/react-dom-shim@npm:10.4.3": + version: 10.4.3 + resolution: "@storybook/react-dom-shim@npm:10.4.3" + peerDependencies: + "@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + "@types/react-dom": ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + storybook: ^10.4.3 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/53a4efc9e19ec101c75cac630cbf2ca09ba9d293c498d6efff0c056589467b1bc9437e6128cc02cc10b4f868c437c1b03302c7e736fc8d843e0779a497a2b81d + languageName: node + linkType: hard + +"@storybook/react-dom-shim@npm:8.6.14": + version: 8.6.14 + resolution: "@storybook/react-dom-shim@npm:8.6.14" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + storybook: ^8.6.14 + checksum: 10c0/6e54c05ab19be1c34084e8acd133d8d358c3b6824db01b4aff159be3f818bd12c3a17217fe1947244c4576d7d02875b486578f011edb0e2290cb62541a263c5f + languageName: node + linkType: hard + +"@storybook/react-vite@npm:^10.4.3": + version: 10.4.3 + resolution: "@storybook/react-vite@npm:10.4.3" + dependencies: + "@joshwooding/vite-plugin-react-docgen-typescript": "npm:^0.7.0" + "@rollup/pluginutils": "npm:^5.0.2" + "@storybook/builder-vite": "npm:10.4.3" + "@storybook/react": "npm:10.4.3" + empathic: "npm:^2.0.0" + magic-string: "npm:^0.30.0" + react-docgen: "npm:^8.0.0" + resolve: "npm:^1.22.8" + tsconfig-paths: "npm:^4.2.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + storybook: ^10.4.3 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: 10c0/16813fca204871fa05b6b53672af571b0184e632b42afb7ef1b15b0c111155eedbcffa621966f1e6b48fa7e17e5bd0213d0f2a5eccb282909ab78e0d61632417 + languageName: node + linkType: hard + +"@storybook/react@npm:10.4.3": + version: 10.4.3 + resolution: "@storybook/react@npm:10.4.3" + dependencies: + "@storybook/global": "npm:^5.0.0" + "@storybook/react-dom-shim": "npm:10.4.3" + react-docgen: "npm:^8.0.2" + react-docgen-typescript: "npm:^2.2.2" + peerDependencies: + "@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + "@types/react-dom": ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + storybook: ^10.4.3 + typescript: ">= 4.9.x" + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + typescript: + optional: true + checksum: 10c0/9cc542fec41868e56d2abb2bb6bb4929f507774aabd6289ab618559a647a2e1b68ceeed047aec98063420144b132dd3e36f240c3f4320574dcd2b28fb1b469ff + languageName: node + linkType: hard + +"@testing-library/jest-dom@npm:^6.9.1": + version: 6.9.1 + resolution: "@testing-library/jest-dom@npm:6.9.1" + dependencies: + "@adobe/css-tools": "npm:^4.4.0" + aria-query: "npm:^5.0.0" + css.escape: "npm:^1.5.1" + dom-accessibility-api: "npm:^0.6.3" + picocolors: "npm:^1.1.1" + redent: "npm:^3.0.0" + checksum: 10c0/4291ebd2f0f38d14cefac142c56c337941775a5807e2a3d6f1a14c2fbd6be76a18e498ed189e95bedc97d9e8cf1738049bc76c85b5bc5e23fae7c9e10f7b3a12 + languageName: node + linkType: hard + +"@testing-library/user-event@npm:^14.6.1": + version: 14.6.1 + resolution: "@testing-library/user-event@npm:14.6.1" + peerDependencies: + "@testing-library/dom": ">=7.21.4" + checksum: 10c0/75fea130a52bf320d35d46ed54f3eec77e71a56911b8b69a3fe29497b0b9947b2dc80d30f04054ad4ce7f577856ae3e5397ea7dff0ef14944d3909784c7a93fe languageName: node linkType: hard @@ -1782,6 +2861,57 @@ __metadata: languageName: node linkType: hard +"@types/babel__core@npm:^7.20.5": + version: 7.20.5 + resolution: "@types/babel__core@npm:7.20.5" + dependencies: + "@babel/parser": "npm:^7.20.7" + "@babel/types": "npm:^7.20.7" + "@types/babel__generator": "npm:*" + "@types/babel__template": "npm:*" + "@types/babel__traverse": "npm:*" + checksum: 10c0/bdee3bb69951e833a4b811b8ee9356b69a61ed5b7a23e1a081ec9249769117fa83aaaf023bb06562a038eb5845155ff663e2d5c75dd95c1d5ccc91db012868ff + languageName: node + linkType: hard + +"@types/babel__generator@npm:*": + version: 7.27.0 + resolution: "@types/babel__generator@npm:7.27.0" + dependencies: + "@babel/types": "npm:^7.0.0" + checksum: 10c0/9f9e959a8792df208a9d048092fda7e1858bddc95c6314857a8211a99e20e6830bdeb572e3587ae8be5429e37f2a96fcf222a9f53ad232f5537764c9e13a2bbd + languageName: node + linkType: hard + +"@types/babel__template@npm:*": + version: 7.4.4 + resolution: "@types/babel__template@npm:7.4.4" + dependencies: + "@babel/parser": "npm:^7.1.0" + "@babel/types": "npm:^7.0.0" + checksum: 10c0/cc84f6c6ab1eab1427e90dd2b76ccee65ce940b778a9a67be2c8c39e1994e6f5bbc8efa309f6cea8dc6754994524cd4d2896558df76d92e7a1f46ecffee7112b + languageName: node + linkType: hard + +"@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.20.7": + version: 7.28.0 + resolution: "@types/babel__traverse@npm:7.28.0" + dependencies: + "@babel/types": "npm:^7.28.2" + checksum: 10c0/b52d7d4e8fc6a9018fe7361c4062c1c190f5778cf2466817cb9ed19d69fbbb54f9a85ffedeb748ed8062d2cf7d4cc088ee739848f47c57740de1c48cbf0d0994 + languageName: node + linkType: hard + +"@types/chai@npm:^5.2.2": + version: 5.2.3 + resolution: "@types/chai@npm:5.2.3" + dependencies: + "@types/deep-eql": "npm:*" + assertion-error: "npm:^2.0.1" + checksum: 10c0/e0ef1de3b6f8045a5e473e867c8565788c444271409d155588504840ad1a53611011f85072188c2833941189400228c1745d78323dac13fcede9c2b28bacfb2f + languageName: node + linkType: hard + "@types/d3-array@npm:^3.0.3": version: 3.2.1 resolution: "@types/d3-array@npm:3.2.1" @@ -1851,6 +2981,20 @@ __metadata: languageName: node linkType: hard +"@types/deep-eql@npm:*": + version: 4.0.2 + resolution: "@types/deep-eql@npm:4.0.2" + checksum: 10c0/bf3f811843117900d7084b9d0c852da9a044d12eb40e6de73b552598a6843c21291a8a381b0532644574beecd5e3491c5ff3a0365ab86b15d59862c025384844 + languageName: node + linkType: hard + +"@types/doctrine@npm:^0.0.9": + version: 0.0.9 + resolution: "@types/doctrine@npm:0.0.9" + checksum: 10c0/cdaca493f13c321cf0cacd1973efc0ae74569633145d9e6fc1128f32217a6968c33bea1f858275239fe90c98f3be57ec8f452b416a9ff48b8e8c1098b20fa51c + languageName: node + linkType: hard + "@types/dompurify@npm:^2.3.3": version: 2.4.0 resolution: "@types/dompurify@npm:2.4.0" @@ -1860,6 +3004,13 @@ __metadata: languageName: node linkType: hard +"@types/estree@npm:^1.0.0": + version: 1.0.9 + resolution: "@types/estree@npm:1.0.9" + checksum: 10c0/3ad3286ca2988cd550dafb8f2ad599c8474868e954fa601a36655bdfefd8039f7c714b8c1c7f2ae219ffbd58bd4660e66fa7479a0120fc02d4777057d4865387 + languageName: node + linkType: hard + "@types/json-schema@npm:^7.0.7": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" @@ -1867,6 +3018,13 @@ __metadata: languageName: node linkType: hard +"@types/mdx@npm:^2.0.0": + version: 2.0.14 + resolution: "@types/mdx@npm:2.0.14" + checksum: 10c0/f1e3873c1e36e2685fb99222bf81a23c55a8e2edf49d0c45cabf2c875b0ae814cd6050cce5770ff1c6881ac747d2ad33731e1de32139b04cf181d8d7e1943ff4 + languageName: node + linkType: hard + "@types/parse-json@npm:^4.0.0": version: 4.0.2 resolution: "@types/parse-json@npm:4.0.2" @@ -1909,6 +3067,13 @@ __metadata: languageName: node linkType: hard +"@types/resolve@npm:^1.20.2": + version: 1.20.6 + resolution: "@types/resolve@npm:1.20.6" + checksum: 10c0/a9b0549d816ff2c353077365d865a33655a141d066d0f5a3ba6fd4b28bc2f4188a510079f7c1f715b3e7af505a27374adce2a5140a3ece2a059aab3d6e1a4244 + languageName: node + linkType: hard + "@types/trusted-types@npm:*": version: 2.0.7 resolution: "@types/trusted-types@npm:2.0.7" @@ -1923,6 +3088,13 @@ __metadata: languageName: node linkType: hard +"@types/uuid@npm:^9.0.1": + version: 9.0.8 + resolution: "@types/uuid@npm:9.0.8" + checksum: 10c0/b411b93054cb1d4361919579ef3508a1f12bf15b5fdd97337d3d351bece6c921b52b6daeef89b62340fd73fd60da407878432a1af777f40648cbe53a01723489 + languageName: node + linkType: hard + "@uiw/codemirror-extensions-basic-setup@npm:4.23.0": version: 4.23.0 resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.23.0" @@ -1986,6 +3158,55 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@npm:3.2.4": + version: 3.2.4 + resolution: "@vitest/expect@npm:3.2.4" + dependencies: + "@types/chai": "npm:^5.2.2" + "@vitest/spy": "npm:3.2.4" + "@vitest/utils": "npm:3.2.4" + chai: "npm:^5.2.0" + tinyrainbow: "npm:^2.0.0" + checksum: 10c0/7586104e3fd31dbe1e6ecaafb9a70131e4197dce2940f727b6a84131eee3decac7b10f9c7c72fa5edbdb68b6f854353bd4c0fa84779e274207fb7379563b10db + languageName: node + linkType: hard + +"@vitest/pretty-format@npm:3.2.4": + version: 3.2.4 + resolution: "@vitest/pretty-format@npm:3.2.4" + dependencies: + tinyrainbow: "npm:^2.0.0" + checksum: 10c0/5ad7d4278e067390d7d633e307fee8103958806a419ca380aec0e33fae71b44a64415f7a9b4bc11635d3c13d4a9186111c581d3cef9c65cc317e68f077456887 + languageName: node + linkType: hard + +"@vitest/spy@npm:3.2.4": + version: 3.2.4 + resolution: "@vitest/spy@npm:3.2.4" + dependencies: + tinyspy: "npm:^4.0.3" + checksum: 10c0/6ebf0b4697dc238476d6b6a60c76ba9eb1dd8167a307e30f08f64149612fd50227682b876420e4c2e09a76334e73f72e3ebf0e350714dc22474258292e202024 + languageName: node + linkType: hard + +"@vitest/utils@npm:3.2.4": + version: 3.2.4 + resolution: "@vitest/utils@npm:3.2.4" + dependencies: + "@vitest/pretty-format": "npm:3.2.4" + loupe: "npm:^3.1.4" + tinyrainbow: "npm:^2.0.0" + checksum: 10c0/024a9b8c8bcc12cf40183c246c244b52ecff861c6deb3477cbf487ac8781ad44c68a9c5fd69f8c1361878e55b97c10d99d511f2597f1f7244b5e5101d028ba64 + languageName: node + linkType: hard + +"@webcontainer/env@npm:^1.1.1": + version: 1.1.1 + resolution: "@webcontainer/env@npm:1.1.1" + checksum: 10c0/bc64114ffa7ee92f4985cc2bdd5e27f6f31d892b9aa5cde68eaf93df02d13ee6edf13faeebdd701464183b6f8f9c47c14975958cdd6fc20e7356ad32f6ee39e7 + languageName: node + linkType: hard + "@wojtekmaj/date-utils@npm:^1.0.2, @wojtekmaj/date-utils@npm:^1.0.3": version: 1.5.1 resolution: "@wojtekmaj/date-utils@npm:1.5.1" @@ -2104,6 +3325,15 @@ __metadata: languageName: node linkType: hard +"acorn@npm:^8.14.0, acorn@npm:^8.15.0": + version: 8.16.0 + resolution: "acorn@npm:8.16.0" + bin: + acorn: bin/acorn + checksum: 10c0/c9c52697227661b68d0debaf972222d4f622aa06b185824164e153438afa7b08273432ca43ea792cadb24dada1d46f6f6bb1ef8de9956979288cc1b96bf9914e + languageName: node + linkType: hard + "acorn@npm:^8.5.0": version: 8.12.1 resolution: "acorn@npm:8.12.1" @@ -2252,6 +3482,29 @@ __metadata: languageName: node linkType: hard +"aria-query@npm:^5.0.0": + version: 5.3.2 + resolution: "aria-query@npm:5.3.2" + checksum: 10c0/003c7e3e2cff5540bf7a7893775fc614de82b0c5dde8ae823d47b7a28a9d4da1f7ed85f340bdb93d5649caa927755f0e31ecc7ab63edfdfc00c8ef07e505e03e + languageName: node + linkType: hard + +"assertion-error@npm:^2.0.1": + version: 2.0.1 + resolution: "assertion-error@npm:2.0.1" + checksum: 10c0/bbbcb117ac6480138f8c93cf7f535614282dea9dc828f540cdece85e3c665e8f78958b96afac52f29ff883c72638e6a87d469ecc9fe5bc902df03ed24a55dba8 + languageName: node + linkType: hard + +"ast-types@npm:^0.16.1": + version: 0.16.1 + resolution: "ast-types@npm:0.16.1" + dependencies: + tslib: "npm:^2.0.1" + checksum: 10c0/abcc49e42eb921a7ebc013d5bec1154651fb6dbc3f497541d488859e681256901b2990b954d530ba0da4d0851271d484f7057d5eff5e07cb73e8b10909f711bf + languageName: node + linkType: hard + "async-limiter@npm:~1.0.0": version: 1.0.1 resolution: "async-limiter@npm:1.0.1" @@ -2291,6 +3544,13 @@ __metadata: languageName: node linkType: hard +"balanced-match@npm:^4.0.2": + version: 4.0.4 + resolution: "balanced-match@npm:4.0.4" + checksum: 10c0/07e86102a3eb2ee2a6a1a89164f29d0dbaebd28f2ca3f5ca786f36b8b23d9e417eb3be45a4acf754f837be5ac0a2317de90d3fcb7f4f4dc95720a1f36b26a17b + languageName: node + linkType: hard + "base64-js@npm:^1.3.1": version: 1.5.1 resolution: "base64-js@npm:1.5.1" @@ -2298,6 +3558,15 @@ __metadata: languageName: node linkType: hard +"baseline-browser-mapping@npm:^2.10.12": + version: 2.10.35 + resolution: "baseline-browser-mapping@npm:2.10.35" + bin: + baseline-browser-mapping: dist/cli.cjs + checksum: 10c0/e92c222d626293925e89c3d5b4a9359f985796e28c37d473ad55b33ef7ed5f9b26cfebbc8620df57512b66049f87120403776f2e603b1a686c469c96047db2b0 + languageName: node + linkType: hard + "boolbase@npm:^1.0.0": version: 1.0.0 resolution: "boolbase@npm:1.0.0" @@ -2314,6 +3583,15 @@ __metadata: languageName: node linkType: hard +"brace-expansion@npm:^5.0.5": + version: 5.0.6 + resolution: "brace-expansion@npm:5.0.6" + dependencies: + balanced-match: "npm:^4.0.2" + checksum: 10c0/8c919869b90f61d533b341d3340be5ee4413232ea89b8246cbc2f38eb014f1d8182785c98a006eaf6111d02dc9eeffefdc240d5ac158625b2ed084dccd4bbf9b + languageName: node + linkType: hard + "browser-process-hrtime@npm:^1.0.0": version: 1.0.0 resolution: "browser-process-hrtime@npm:1.0.0" @@ -2321,6 +3599,21 @@ __metadata: languageName: node linkType: hard +"browserslist@npm:^4.24.0": + version: 4.28.2 + resolution: "browserslist@npm:4.28.2" + dependencies: + baseline-browser-mapping: "npm:^2.10.12" + caniuse-lite: "npm:^1.0.30001782" + electron-to-chromium: "npm:^1.5.328" + node-releases: "npm:^2.0.36" + update-browserslist-db: "npm:^1.2.3" + bin: + browserslist: cli.js + checksum: 10c0/c0228b6330f785b7fa59d2d360124ec6d9322f96ed9f3ee1f873e33ecc9503a6f0ffc3b71191a28c4ff6e930b753b30043da1c33844a9548f3018d491f09ce60 + languageName: node + linkType: hard + "buffer@npm:^5.5.0, buffer@npm:^5.6.0": version: 5.7.1 resolution: "buffer@npm:5.7.1" @@ -2341,6 +3634,15 @@ __metadata: languageName: node linkType: hard +"bundle-name@npm:^4.1.0": + version: 4.1.0 + resolution: "bundle-name@npm:4.1.0" + dependencies: + run-applescript: "npm:^7.0.0" + checksum: 10c0/8e575981e79c2bcf14d8b1c027a3775c095d362d1382312f444a7c861b0e21513c0bd8db5bd2b16e50ba0709fa622d4eab6b53192d222120305e68359daece29 + languageName: node + linkType: hard + "cacache@npm:^19.0.1": version: 19.0.1 resolution: "cacache@npm:19.0.1" @@ -2375,6 +3677,26 @@ __metadata: languageName: node linkType: hard +"caniuse-lite@npm:^1.0.30001782": + version: 1.0.30001799 + resolution: "caniuse-lite@npm:1.0.30001799" + checksum: 10c0/f24f9834edc7b60188f368ce44714695c3901bc4acb7f2a977dd9b7b697e39ddc0f9947fad6224a955b789f36a73432cb888d620aa7280d728f582d3bd8927a7 + languageName: node + linkType: hard + +"chai@npm:^5.2.0": + version: 5.3.3 + resolution: "chai@npm:5.3.3" + dependencies: + assertion-error: "npm:^2.0.1" + check-error: "npm:^2.1.1" + deep-eql: "npm:^5.0.1" + loupe: "npm:^3.1.0" + pathval: "npm:^2.0.0" + checksum: 10c0/b360fd4d38861622e5010c2f709736988b05c7f31042305fa3f4e9911f6adb80ccfb4e302068bf8ed10e835c2e2520cba0f5edc13d878b886987e5aa62483f53 + languageName: node + linkType: hard + "chalk@npm:^2.4.2": version: 2.4.2 resolution: "chalk@npm:2.4.2" @@ -2386,6 +3708,13 @@ __metadata: languageName: node linkType: hard +"check-error@npm:^2.1.1": + version: 2.1.3 + resolution: "check-error@npm:2.1.3" + checksum: 10c0/878e99038fb6476316b74668cd6a498c7e66df3efe48158fa40db80a06ba4258742ac3ee2229c4a2a98c5e73f5dff84eb3e50ceb6b65bbd8f831eafc8338607d + languageName: node + linkType: hard + "cheerio-select@npm:^1.5.0": version: 1.6.0 resolution: "cheerio-select@npm:1.6.0" @@ -2597,6 +3926,13 @@ __metadata: languageName: node linkType: hard +"convert-source-map@npm:^2.0.0": + version: 2.0.0 + resolution: "convert-source-map@npm:2.0.0" + checksum: 10c0/8f2f7a27a1a011cc6cc88cc4da2d7d0cfa5ee0369508baae3d98c260bb3ac520691464e5bbe4ae7cdf09860c1d69ecc6f70c63c6e7c7f7e3f18ec08484dc7d9b + languageName: node + linkType: hard + "cookie@npm:^1.0.1": version: 1.1.1 resolution: "cookie@npm:1.1.1" @@ -2687,6 +4023,13 @@ __metadata: languageName: node linkType: hard +"css.escape@npm:^1.5.1": + version: 1.5.1 + resolution: "css.escape@npm:1.5.1" + checksum: 10c0/5e09035e5bf6c2c422b40c6df2eb1529657a17df37fda5d0433d722609527ab98090baf25b13970ca754079a0f3161dd3dfc0e743563ded8cfa0749d861c1525 + languageName: node + linkType: hard + "cssom@npm:^0.5.0": version: 0.5.0 resolution: "cssom@npm:0.5.0" @@ -2854,6 +4197,18 @@ __metadata: languageName: node linkType: hard +"debug@npm:^4.1.0": + version: 4.4.3 + resolution: "debug@npm:4.4.3" + dependencies: + ms: "npm:^2.1.3" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10c0/d79136ec6c83ecbefd0f6a5593da6a9c91ec4d7ddc4b54c883d6e71ec9accb5f67a1a5e96d00a328196b5b5c86d365e98d8a3a70856aaf16b4e7b1985e67f5a6 + languageName: node + linkType: hard + "debug@npm:^4.3.4": version: 4.4.1 resolution: "debug@npm:4.4.1" @@ -2892,6 +4247,13 @@ __metadata: languageName: node linkType: hard +"deep-eql@npm:^5.0.1": + version: 5.0.2 + resolution: "deep-eql@npm:5.0.2" + checksum: 10c0/7102cf3b7bb719c6b9c0db2e19bf0aa9318d141581befe8c7ce8ccd39af9eaa4346e5e05adef7f9bd7015da0f13a3a25dcfe306ef79dc8668aedbecb658dd247 + languageName: node + linkType: hard + "deepmerge@npm:^2.1.1": version: 2.2.1 resolution: "deepmerge@npm:2.2.1" @@ -2906,6 +4268,23 @@ __metadata: languageName: node linkType: hard +"default-browser-id@npm:^5.0.0": + version: 5.0.1 + resolution: "default-browser-id@npm:5.0.1" + checksum: 10c0/5288b3094c740ef3a86df9b999b04ff5ba4dee6b64e7b355c0fff5217752c8c86908d67f32f6cba9bb4f9b7b61a1b640c0a4f9e34c57e0ff3493559a625245ee + languageName: node + linkType: hard + +"default-browser@npm:^5.2.1": + version: 5.5.0 + resolution: "default-browser@npm:5.5.0" + dependencies: + bundle-name: "npm:^4.1.0" + default-browser-id: "npm:^5.0.0" + checksum: 10c0/576593b617b17a7223014b4571bfe1c06a2581a4eb8b130985d90d253afa3f40999caec70eb0e5776e80d4af6a41cce91018cd3f86e57ad578bf59e46fb19abe + languageName: node + linkType: hard + "deferred-leveldown@npm:~5.3.0": version: 5.3.0 resolution: "deferred-leveldown@npm:5.3.0" @@ -2916,6 +4295,13 @@ __metadata: languageName: node linkType: hard +"define-lazy-prop@npm:^3.0.0": + version: 3.0.0 + resolution: "define-lazy-prop@npm:3.0.0" + checksum: 10c0/5ab0b2bf3fa58b3a443140bbd4cd3db1f91b985cc8a246d330b9ac3fc0b6a325a6d82bddc0b055123d745b3f9931afeea74a5ec545439a1630b9c8512b0eeb49 + languageName: node + linkType: hard + "delayed-stream@npm:~1.0.0": version: 1.0.0 resolution: "delayed-stream@npm:1.0.0" @@ -2944,6 +4330,22 @@ __metadata: languageName: node linkType: hard +"doctrine@npm:^3.0.0": + version: 3.0.0 + resolution: "doctrine@npm:3.0.0" + dependencies: + esutils: "npm:^2.0.2" + checksum: 10c0/c96bdccabe9d62ab6fea9399fdff04a66e6563c1d6fb3a3a063e8d53c3bb136ba63e84250bbf63d00086a769ad53aef92d2bd483f03f837fc97b71cbee6b2520 + languageName: node + linkType: hard + +"dom-accessibility-api@npm:^0.6.3": + version: 0.6.3 + resolution: "dom-accessibility-api@npm:0.6.3" + checksum: 10c0/10bee5aa514b2a9a37c87cd81268db607a2e933a050074abc2f6fa3da9080ebed206a320cbc123567f2c3087d22292853bdfdceaffdd4334ffe2af9510b29360 + languageName: node + linkType: hard + "dom-align@npm:^1.7.0": version: 1.12.4 resolution: "dom-align@npm:1.12.4" @@ -3022,6 +4424,13 @@ __metadata: languageName: node linkType: hard +"electron-to-chromium@npm:^1.5.328": + version: 1.5.371 + resolution: "electron-to-chromium@npm:1.5.371" + checksum: 10c0/d5d160d884f8200ef95ee9f0a2484d79b4a9f7363c908d5309ad460c79f627d5a8dd23a1288d0de1690a74bac0de34a5ca4383270c7d27231908f1b4b43287ef + languageName: node + linkType: hard + "emoji-regex@npm:^8.0.0": version: 8.0.0 resolution: "emoji-regex@npm:8.0.0" @@ -3036,6 +4445,13 @@ __metadata: languageName: node linkType: hard +"empathic@npm:^2.0.0": + version: 2.0.1 + resolution: "empathic@npm:2.0.1" + checksum: 10c0/577f2868bfcad4ffbf911b57c75016125eb8cc8a7d32cf2d3e9fbcb31bfe6e9e6b66d9457ac34ccb2cd38bff353b3af34287899e0360b8c561ff6d4a048aca62 + languageName: node + linkType: hard + "encoding-down@npm:^6.3.0": version: 6.3.0 resolution: "encoding-down@npm:6.3.0" @@ -3105,6 +4521,13 @@ __metadata: languageName: node linkType: hard +"es-errors@npm:^1.3.0": + version: 1.3.0 + resolution: "es-errors@npm:1.3.0" + checksum: 10c0/0a61325670072f98d8ae3b914edab3559b6caa980f08054a3b872052640d91da01d38df55df797fcc916389d77fc92b8d5906cf028f4db46d7e3003abecbca85 + languageName: node + linkType: hard + "es-toolkit@npm:^1.39.3": version: 1.46.1 resolution: "es-toolkit@npm:1.46.1" @@ -3117,6 +4540,102 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.26.0 || ^0.27.0": + version: 0.27.7 + resolution: "esbuild@npm:0.27.7" + dependencies: + "@esbuild/aix-ppc64": "npm:0.27.7" + "@esbuild/android-arm": "npm:0.27.7" + "@esbuild/android-arm64": "npm:0.27.7" + "@esbuild/android-x64": "npm:0.27.7" + "@esbuild/darwin-arm64": "npm:0.27.7" + "@esbuild/darwin-x64": "npm:0.27.7" + "@esbuild/freebsd-arm64": "npm:0.27.7" + "@esbuild/freebsd-x64": "npm:0.27.7" + "@esbuild/linux-arm": "npm:0.27.7" + "@esbuild/linux-arm64": "npm:0.27.7" + "@esbuild/linux-ia32": "npm:0.27.7" + "@esbuild/linux-loong64": "npm:0.27.7" + "@esbuild/linux-mips64el": "npm:0.27.7" + "@esbuild/linux-ppc64": "npm:0.27.7" + "@esbuild/linux-riscv64": "npm:0.27.7" + "@esbuild/linux-s390x": "npm:0.27.7" + "@esbuild/linux-x64": "npm:0.27.7" + "@esbuild/netbsd-arm64": "npm:0.27.7" + "@esbuild/netbsd-x64": "npm:0.27.7" + "@esbuild/openbsd-arm64": "npm:0.27.7" + "@esbuild/openbsd-x64": "npm:0.27.7" + "@esbuild/openharmony-arm64": "npm:0.27.7" + "@esbuild/sunos-x64": "npm:0.27.7" + "@esbuild/win32-arm64": "npm:0.27.7" + "@esbuild/win32-ia32": "npm:0.27.7" + "@esbuild/win32-x64": "npm:0.27.7" + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-arm64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-arm64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/openharmony-arm64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 10c0/ccd51f0555708bc9ff4ec9dc3ac92d3daacd45ecaac949ca8645984c5c323bf8cefe98c2df307418685e0b4ce37f9a3bdbfe8e3651fe632a0059a436195a17d4 + languageName: node + linkType: hard + +"escalade@npm:^3.2.0": + version: 3.2.0 + resolution: "escalade@npm:3.2.0" + checksum: 10c0/ced4dd3a78e15897ed3be74e635110bbf3b08877b0a41be50dcb325ee0e0b5f65fc2d50e9845194d7c4633f327e2e1c6cce00a71b617c5673df0374201d67f65 + languageName: node + linkType: hard + "escape-string-regexp@npm:^1.0.5": version: 1.0.5 resolution: "escape-string-regexp@npm:1.0.5" @@ -3156,7 +4675,7 @@ __metadata: languageName: node linkType: hard -"esprima@npm:^4.0.1": +"esprima@npm:^4.0.1, esprima@npm:~4.0.0": version: 4.0.1 resolution: "esprima@npm:4.0.1" bin: @@ -3173,6 +4692,13 @@ __metadata: languageName: node linkType: hard +"estree-walker@npm:^2.0.2": + version: 2.0.2 + resolution: "estree-walker@npm:2.0.2" + checksum: 10c0/53a6c54e2019b8c914dc395890153ffdc2322781acf4bd7d1a32d7aedc1710807bdcd866ac133903d5629ec601fbb50abe8c2e5553c7f5a0afdd9b6af6c945af + languageName: node + linkType: hard + "esutils@npm:^2.0.2": version: 2.0.3 resolution: "esutils@npm:2.0.3" @@ -3370,6 +4896,13 @@ __metadata: languageName: node linkType: hard +"gensync@npm:^1.0.0-beta.2": + version: 1.0.0-beta.2 + resolution: "gensync@npm:1.0.0-beta.2" + checksum: 10c0/782aba6cba65b1bb5af3b095d96249d20edbe8df32dbf4696fd49be2583faf676173bf4809386588828e4dd76a3354fcbeb577bab1c833ccd9fc4577f26103f8 + languageName: node + linkType: hard + "get-browser-rtc@npm:^1.1.0": version: 1.1.0 resolution: "get-browser-rtc@npm:1.1.0" @@ -3402,6 +4935,17 @@ __metadata: languageName: node linkType: hard +"glob@npm:^13.0.1": + version: 13.0.6 + resolution: "glob@npm:13.0.6" + dependencies: + minimatch: "npm:^10.2.2" + minipass: "npm:^7.1.3" + path-scurry: "npm:^2.0.2" + checksum: 10c0/269c236f11a9b50357fe7a8c6aadac667e01deb5242b19c84975628f05f4438d8ee1354bb62c5d6c10f37fd59911b54d7799730633a2786660d8c69f1d18120a + languageName: node + linkType: hard + "globals@npm:^11.1.0": version: 11.12.0 resolution: "globals@npm:11.12.0" @@ -3469,6 +5013,15 @@ __metadata: languageName: node linkType: hard +"hasown@npm:^2.0.3": + version: 2.0.4 + resolution: "hasown@npm:2.0.4" + dependencies: + function-bind: "npm:^1.1.2" + checksum: 10c0/2d8de939e270b70618f8cebb69746620db10617dbb495bc66ddad326955ea24d3ca4af133aff3eb7c1853e0218f867bc2b050ec26fe02e3aea58f880ffc5e506 + languageName: node + linkType: hard + "highlight.js@npm:^10.1.1": version: 10.7.3 resolution: "highlight.js@npm:10.7.3" @@ -3635,6 +5188,13 @@ __metadata: languageName: node linkType: hard +"indent-string@npm:^4.0.0": + version: 4.0.0 + resolution: "indent-string@npm:4.0.0" + checksum: 10c0/1e1904ddb0cb3d6cce7cd09e27a90184908b7a5d5c21b92e232c93579d314f0b83c246ffb035493d0504b1e9147ba2c9b21df0030f48673fba0496ecd698161f + languageName: node + linkType: hard + "inherits@npm:^2.0.3, inherits@npm:^2.0.4": version: 2.0.4 resolution: "inherits@npm:2.0.4" @@ -3705,6 +5265,24 @@ __metadata: languageName: node linkType: hard +"is-core-module@npm:^2.16.1": + version: 2.16.2 + resolution: "is-core-module@npm:2.16.2" + dependencies: + hasown: "npm:^2.0.3" + checksum: 10c0/14b4258390283709c15476d023ec173e27458d5d014ccdb8ed39d576e551c3fa45498b7c9fe178f1529c4cb2648ddd58852a6a62107a019f6e349529f277518a + languageName: node + linkType: hard + +"is-docker@npm:^3.0.0": + version: 3.0.0 + resolution: "is-docker@npm:3.0.0" + bin: + is-docker: cli.js + checksum: 10c0/d2c4f8e6d3e34df75a5defd44991b6068afad4835bb783b902fa12d13ebdb8f41b2a199dcb0b5ed2cb78bfee9e4c0bbdb69c2d9646f4106464674d3e697a5856 + languageName: node + linkType: hard + "is-fullwidth-code-point@npm:^3.0.0": version: 3.0.0 resolution: "is-fullwidth-code-point@npm:3.0.0" @@ -3712,6 +5290,17 @@ __metadata: languageName: node linkType: hard +"is-inside-container@npm:^1.0.0": + version: 1.0.0 + resolution: "is-inside-container@npm:1.0.0" + dependencies: + is-docker: "npm:^3.0.0" + bin: + is-inside-container: cli.js + checksum: 10c0/a8efb0e84f6197e6ff5c64c52890fa9acb49b7b74fed4da7c95383965da6f0fa592b4dbd5e38a79f87fc108196937acdbcd758fcefc9b140e479b39ce1fcd1cd + languageName: node + linkType: hard + "is-mobile@npm:^5.0.0": version: 5.0.0 resolution: "is-mobile@npm:5.0.0" @@ -3733,6 +5322,15 @@ __metadata: languageName: node linkType: hard +"is-wsl@npm:^3.1.0": + version: 3.1.1 + resolution: "is-wsl@npm:3.1.1" + dependencies: + is-inside-container: "npm:^1.0.0" + checksum: 10c0/7e5023522bfb8f27de4de960b0d82c4a8146c0bddb186529a3616d78b5bbbfc19ef0c5fc60d0b3a3cc0bf95a415fbdedc18454310ea3049587c879b07ace5107 + languageName: node + linkType: hard + "isexe@npm:^2.0.0": version: 2.0.0 resolution: "isexe@npm:2.0.0" @@ -3841,6 +5439,15 @@ __metadata: languageName: node linkType: hard +"jsesc@npm:^3.0.2": + version: 3.1.0 + resolution: "jsesc@npm:3.1.0" + bin: + jsesc: bin/jsesc + checksum: 10c0/531779df5ec94f47e462da26b4cbf05eb88a83d9f08aac2ba04206508fc598527a153d08bd462bae82fc78b3eaa1a908e1a4a79f886e9238641c4cdefaf118b1 + languageName: node + linkType: hard + "json-parse-even-better-errors@npm:^2.3.0": version: 2.3.1 resolution: "json-parse-even-better-errors@npm:2.3.1" @@ -3884,6 +5491,15 @@ __metadata: languageName: node linkType: hard +"json5@npm:^2.2.2, json5@npm:^2.2.3": + version: 2.2.3 + resolution: "json5@npm:2.2.3" + bin: + json5: lib/cli.js + checksum: 10c0/5a04eed94810fa55c5ea138b2f7a5c12b97c3750bc63d11e511dcecbfef758003861522a070c2272764ee0f4e3e323862f386945aeb5b85b87ee43f084ba586c + languageName: node + linkType: hard + "jsonpointer@npm:^5.0.0": version: 5.0.1 resolution: "jsonpointer@npm:5.0.1" @@ -3905,6 +5521,8 @@ __metadata: "@dnd-kit/utilities": "npm:^3.2.2" "@fontsource/roboto": "npm:^4.5.8" "@rjsf/core": "npm:4.2.3" + "@storybook/addon-essentials": "npm:8.6.14" + "@storybook/react-vite": "npm:^10.4.3" "@types/react": "npm:^19.2.14" "@uiw/react-codemirror": "npm:^4.21.20" antd: "npm:^6.3.7" @@ -3954,6 +5572,7 @@ __metadata: recharts: "npm:^3.8.1" regenerator-runtime: "npm:^0.13.7" split-pane-react: "npm:^0.1.3" + storybook: "npm:^10.4.3" striptags: "npm:^3.1.1" styled-components: "npm:^6.4.1" wax-prosemirror-core: "npm:0.10.2" @@ -4250,6 +5869,13 @@ __metadata: languageName: node linkType: hard +"loupe@npm:^3.1.0, loupe@npm:^3.1.4": + version: 3.2.1 + resolution: "loupe@npm:3.2.1" + checksum: 10c0/910c872cba291309664c2d094368d31a68907b6f5913e989d301b5c25f30e97d76d77f23ab3bf3b46d0f601ff0b6af8810c10c31b91d2c6b2f132809ca2cc705 + languageName: node + linkType: hard + "lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": version: 10.4.3 resolution: "lru-cache@npm:10.4.3" @@ -4257,6 +5883,22 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:^11.0.0": + version: 11.5.1 + resolution: "lru-cache@npm:11.5.1" + checksum: 10c0/7b341cea79a8efe9c6a6f20c8757a77eca5b25d7ff983ccf4e11e547b81f6787824baa1c84705251dff84ab4ffac85717ac354b9d02e465f86a9f8b166409979 + languageName: node + linkType: hard + +"lru-cache@npm:^5.1.1": + version: 5.1.1 + resolution: "lru-cache@npm:5.1.1" + dependencies: + yallist: "npm:^3.0.2" + checksum: 10c0/89b2ef2ef45f543011e38737b8a8622a2f8998cddf0e5437174ef8f1f70a8b9d14a918ab3e232cb3ba343b7abddffa667f0b59075b2b80e6b4d63c3de6127482 + languageName: node + linkType: hard + "ltgt@npm:^2.1.2": version: 2.2.1 resolution: "ltgt@npm:2.2.1" @@ -4264,6 +5906,15 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.30.0": + version: 0.30.21 + resolution: "magic-string@npm:0.30.21" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.5.5" + checksum: 10c0/299378e38f9a270069fc62358522ddfb44e94244baa0d6a8980ab2a9b2490a1d03b236b447eee309e17eb3bddfa482c61259d47960eb018a904f0ded52780c4a + languageName: node + linkType: hard + "make-event-props@npm:^1.1.0": version: 1.6.2 resolution: "make-event-props@npm:1.6.2" @@ -4290,6 +5941,13 @@ __metadata: languageName: node linkType: hard +"map-or-similar@npm:^1.5.0": + version: 1.5.0 + resolution: "map-or-similar@npm:1.5.0" + checksum: 10c0/33c6ccfdc272992e33e4e99a69541a3e7faed9de3ac5bc732feb2500a9ee71d3f9d098980a70b7746e7eeb7f859ff7dfb8aa9b5ecc4e34170a32ab78cfb18def + languageName: node + linkType: hard + "mathjax-full@npm:3.1.4": version: 3.1.4 resolution: "mathjax-full@npm:3.1.4" @@ -4308,6 +5966,15 @@ __metadata: languageName: node linkType: hard +"memoizerific@npm:^1.11.3": + version: 1.11.3 + resolution: "memoizerific@npm:1.11.3" + dependencies: + map-or-similar: "npm:^1.5.0" + checksum: 10c0/661bf69b7afbfad57f0208f0c63324f4c96087b480708115b78ee3f0237d86c7f91347f6db31528740b2776c2e34c709bcb034e1e910edee2270c9603a0a469e + languageName: node + linkType: hard + "merge-class-names@npm:^1.1.1": version: 1.4.2 resolution: "merge-class-names@npm:1.4.2" @@ -4343,6 +6010,22 @@ __metadata: languageName: node linkType: hard +"min-indent@npm:^1.0.0": + version: 1.0.1 + resolution: "min-indent@npm:1.0.1" + checksum: 10c0/7e207bd5c20401b292de291f02913230cb1163abca162044f7db1d951fa245b174dc00869d40dd9a9f32a885ad6a5f3e767ee104cf278f399cb4e92d3f582d5c + languageName: node + linkType: hard + +"minimatch@npm:^10.2.2": + version: 10.2.5 + resolution: "minimatch@npm:10.2.5" + dependencies: + brace-expansion: "npm:^5.0.5" + checksum: 10c0/6bb058bd6324104b9ec2f763476a35386d05079c1f5fe4fbf1f324a25237cd4534d6813ecd71f48208f4e635c1221899bef94c3c89f7df55698fe373aaae20fd + languageName: node + linkType: hard + "minimatch@npm:^9.0.4": version: 9.0.5 resolution: "minimatch@npm:9.0.5" @@ -4352,6 +6035,13 @@ __metadata: languageName: node linkType: hard +"minimist@npm:^1.2.6": + version: 1.2.8 + resolution: "minimist@npm:1.2.8" + checksum: 10c0/19d3fcdca050087b84c2029841a093691a91259a47def2f18222f41e7645a0b7c44ef4b40e88a1e58a40c84d2ef0ee6047c55594d298146d0eb3f6b737c20ce6 + languageName: node + linkType: hard + "minipass-collect@npm:^2.0.1": version: 2.0.1 resolution: "minipass-collect@npm:2.0.1" @@ -4419,6 +6109,13 @@ __metadata: languageName: node linkType: hard +"minipass@npm:^7.1.3": + version: 7.1.3 + resolution: "minipass@npm:7.1.3" + checksum: 10c0/539da88daca16533211ea5a9ee98dc62ff5742f531f54640dd34429e621955e91cc280a91a776026264b7f9f6735947629f920944e9c1558369e8bf22eb33fbb + languageName: node + linkType: hard + "minizlib@npm:^3.0.1": version: 3.0.2 resolution: "minizlib@npm:3.0.2" @@ -4553,6 +6250,13 @@ __metadata: languageName: node linkType: hard +"node-releases@npm:^2.0.36": + version: 2.0.47 + resolution: "node-releases@npm:2.0.47" + checksum: 10c0/fb1a703adb88c3bfe73aa39ebe0a0bc6d59c9d20d74ad61fb50958ffb22840da82a7a256076840b84c8ed57bb80e6fc8e588e675712fcf7af269aab16206b9b5 + languageName: node + linkType: hard + "nopt@npm:^8.0.0": version: 8.1.0 resolution: "nopt@npm:8.1.0" @@ -4587,6 +6291,18 @@ __metadata: languageName: node linkType: hard +"open@npm:^10.2.0": + version: 10.2.0 + resolution: "open@npm:10.2.0" + dependencies: + default-browser: "npm:^5.2.1" + define-lazy-prop: "npm:^3.0.0" + is-inside-container: "npm:^1.0.0" + wsl-utils: "npm:^0.1.0" + checksum: 10c0/5a36d0c1fd2f74ce553beb427ca8b8494b623fc22c6132d0c1688f246a375e24584ea0b44c67133d9ab774fa69be8e12fbe1ff12504b1142bd960fb09671948f + languageName: node + linkType: hard + "optimism@npm:^0.18.0": version: 0.18.0 resolution: "optimism@npm:0.18.0" @@ -4606,6 +6322,142 @@ __metadata: languageName: node linkType: hard +"oxc-parser@npm:^0.127.0": + version: 0.127.0 + resolution: "oxc-parser@npm:0.127.0" + dependencies: + "@oxc-parser/binding-android-arm-eabi": "npm:0.127.0" + "@oxc-parser/binding-android-arm64": "npm:0.127.0" + "@oxc-parser/binding-darwin-arm64": "npm:0.127.0" + "@oxc-parser/binding-darwin-x64": "npm:0.127.0" + "@oxc-parser/binding-freebsd-x64": "npm:0.127.0" + "@oxc-parser/binding-linux-arm-gnueabihf": "npm:0.127.0" + "@oxc-parser/binding-linux-arm-musleabihf": "npm:0.127.0" + "@oxc-parser/binding-linux-arm64-gnu": "npm:0.127.0" + "@oxc-parser/binding-linux-arm64-musl": "npm:0.127.0" + "@oxc-parser/binding-linux-ppc64-gnu": "npm:0.127.0" + "@oxc-parser/binding-linux-riscv64-gnu": "npm:0.127.0" + "@oxc-parser/binding-linux-riscv64-musl": "npm:0.127.0" + "@oxc-parser/binding-linux-s390x-gnu": "npm:0.127.0" + "@oxc-parser/binding-linux-x64-gnu": "npm:0.127.0" + "@oxc-parser/binding-linux-x64-musl": "npm:0.127.0" + "@oxc-parser/binding-openharmony-arm64": "npm:0.127.0" + "@oxc-parser/binding-wasm32-wasi": "npm:0.127.0" + "@oxc-parser/binding-win32-arm64-msvc": "npm:0.127.0" + "@oxc-parser/binding-win32-ia32-msvc": "npm:0.127.0" + "@oxc-parser/binding-win32-x64-msvc": "npm:0.127.0" + "@oxc-project/types": "npm:^0.127.0" + dependenciesMeta: + "@oxc-parser/binding-android-arm-eabi": + optional: true + "@oxc-parser/binding-android-arm64": + optional: true + "@oxc-parser/binding-darwin-arm64": + optional: true + "@oxc-parser/binding-darwin-x64": + optional: true + "@oxc-parser/binding-freebsd-x64": + optional: true + "@oxc-parser/binding-linux-arm-gnueabihf": + optional: true + "@oxc-parser/binding-linux-arm-musleabihf": + optional: true + "@oxc-parser/binding-linux-arm64-gnu": + optional: true + "@oxc-parser/binding-linux-arm64-musl": + optional: true + "@oxc-parser/binding-linux-ppc64-gnu": + optional: true + "@oxc-parser/binding-linux-riscv64-gnu": + optional: true + "@oxc-parser/binding-linux-riscv64-musl": + optional: true + "@oxc-parser/binding-linux-s390x-gnu": + optional: true + "@oxc-parser/binding-linux-x64-gnu": + optional: true + "@oxc-parser/binding-linux-x64-musl": + optional: true + "@oxc-parser/binding-openharmony-arm64": + optional: true + "@oxc-parser/binding-wasm32-wasi": + optional: true + "@oxc-parser/binding-win32-arm64-msvc": + optional: true + "@oxc-parser/binding-win32-ia32-msvc": + optional: true + "@oxc-parser/binding-win32-x64-msvc": + optional: true + checksum: 10c0/9d109fb3a79c0862a36434cc01c8c0e8f6cf5f1efe9369e02d2183fd518479b10262cf092da2e7f8328befae446afa05ccf742ce12f8346d81429c8f2cdf1651 + languageName: node + linkType: hard + +"oxc-resolver@npm:^11.19.1": + version: 11.20.0 + resolution: "oxc-resolver@npm:11.20.0" + dependencies: + "@oxc-resolver/binding-android-arm-eabi": "npm:11.20.0" + "@oxc-resolver/binding-android-arm64": "npm:11.20.0" + "@oxc-resolver/binding-darwin-arm64": "npm:11.20.0" + "@oxc-resolver/binding-darwin-x64": "npm:11.20.0" + "@oxc-resolver/binding-freebsd-x64": "npm:11.20.0" + "@oxc-resolver/binding-linux-arm-gnueabihf": "npm:11.20.0" + "@oxc-resolver/binding-linux-arm-musleabihf": "npm:11.20.0" + "@oxc-resolver/binding-linux-arm64-gnu": "npm:11.20.0" + "@oxc-resolver/binding-linux-arm64-musl": "npm:11.20.0" + "@oxc-resolver/binding-linux-ppc64-gnu": "npm:11.20.0" + "@oxc-resolver/binding-linux-riscv64-gnu": "npm:11.20.0" + "@oxc-resolver/binding-linux-riscv64-musl": "npm:11.20.0" + "@oxc-resolver/binding-linux-s390x-gnu": "npm:11.20.0" + "@oxc-resolver/binding-linux-x64-gnu": "npm:11.20.0" + "@oxc-resolver/binding-linux-x64-musl": "npm:11.20.0" + "@oxc-resolver/binding-openharmony-arm64": "npm:11.20.0" + "@oxc-resolver/binding-wasm32-wasi": "npm:11.20.0" + "@oxc-resolver/binding-win32-arm64-msvc": "npm:11.20.0" + "@oxc-resolver/binding-win32-x64-msvc": "npm:11.20.0" + dependenciesMeta: + "@oxc-resolver/binding-android-arm-eabi": + optional: true + "@oxc-resolver/binding-android-arm64": + optional: true + "@oxc-resolver/binding-darwin-arm64": + optional: true + "@oxc-resolver/binding-darwin-x64": + optional: true + "@oxc-resolver/binding-freebsd-x64": + optional: true + "@oxc-resolver/binding-linux-arm-gnueabihf": + optional: true + "@oxc-resolver/binding-linux-arm-musleabihf": + optional: true + "@oxc-resolver/binding-linux-arm64-gnu": + optional: true + "@oxc-resolver/binding-linux-arm64-musl": + optional: true + "@oxc-resolver/binding-linux-ppc64-gnu": + optional: true + "@oxc-resolver/binding-linux-riscv64-gnu": + optional: true + "@oxc-resolver/binding-linux-riscv64-musl": + optional: true + "@oxc-resolver/binding-linux-s390x-gnu": + optional: true + "@oxc-resolver/binding-linux-x64-gnu": + optional: true + "@oxc-resolver/binding-linux-x64-musl": + optional: true + "@oxc-resolver/binding-openharmony-arm64": + optional: true + "@oxc-resolver/binding-wasm32-wasi": + optional: true + "@oxc-resolver/binding-win32-arm64-msvc": + optional: true + "@oxc-resolver/binding-win32-x64-msvc": + optional: true + checksum: 10c0/4a0b0fae7a8b8a25d5173aaeb7348c53d5f60d5bb37a66c3177dcf416319d1f7065b625afa37b924a288dec5b401ba92b003cbce26b91e6631bd8690052c80de + languageName: node + linkType: hard + "p-map@npm:^7.0.2": version: 7.0.3 resolution: "p-map@npm:7.0.3" @@ -4681,6 +6533,16 @@ __metadata: languageName: node linkType: hard +"path-scurry@npm:^2.0.2": + version: 2.0.2 + resolution: "path-scurry@npm:2.0.2" + dependencies: + lru-cache: "npm:^11.0.0" + minipass: "npm:^7.1.2" + checksum: 10c0/b35ad37cf6557a87fd057121ce2be7695380c9138d93e87ae928609da259ea0a170fac6f3ef1eb3ece8a068e8b7f2f3adf5bb2374cf4d4a57fe484954fcc9482 + languageName: node + linkType: hard + "path-type@npm:^4.0.0": version: 4.0.0 resolution: "path-type@npm:4.0.0" @@ -4688,6 +6550,13 @@ __metadata: languageName: node linkType: hard +"pathval@npm:^2.0.0": + version: 2.0.1 + resolution: "pathval@npm:2.0.1" + checksum: 10c0/460f4709479fbf2c45903a65655fc8f0a5f6d808f989173aeef5fdea4ff4f303dc13f7870303999add60ec49d4c14733895c0a869392e9866f1091fa64fd7581 + languageName: node + linkType: hard + "peek-readable@npm:^7.0.0": version: 7.0.0 resolution: "peek-readable@npm:7.0.0" @@ -4716,13 +6585,22 @@ __metadata: languageName: node linkType: hard -"picomatch@npm:^4.0.4": +"picomatch@npm:^4.0.3, picomatch@npm:^4.0.4": version: 4.0.4 resolution: "picomatch@npm:4.0.4" checksum: 10c0/e2c6023372cc7b5764719a5ffb9da0f8e781212fa7ca4bd0562db929df8e117460f00dff3cb7509dacfc06b86de924b247f504d0ce1806a37fac4633081466b0 languageName: node linkType: hard +"polished@npm:^4.2.2": + version: 4.3.1 + resolution: "polished@npm:4.3.1" + dependencies: + "@babel/runtime": "npm:^7.17.8" + checksum: 10c0/45480d4c7281a134281cef092f6ecc202a868475ff66a390fee6e9261386e16f3047b4de46a2f2e1cf7fb7aa8f52d30b4ed631a1e3bcd6f303ca31161d4f07fe + languageName: node + linkType: hard + "postcss-value-parser@npm:^4.0.2": version: 4.2.0 resolution: "postcss-value-parser@npm:4.2.0" @@ -5192,6 +7070,44 @@ __metadata: languageName: node linkType: hard +"react-docgen-typescript@npm:^2.2.2": + version: 2.4.0 + resolution: "react-docgen-typescript@npm:2.4.0" + peerDependencies: + typescript: ">= 4.3.x" + checksum: 10c0/18e3e1c80d28abcdd72e62261d2f70b0904d9b088f9c2ebe485ffee5e46f5735208bc174a20ed2772112b3ca6432b5f3d5f0ac345872fe76e541f84543e49e50 + languageName: node + linkType: hard + +"react-docgen@npm:^8.0.0, react-docgen@npm:^8.0.2": + version: 8.0.3 + resolution: "react-docgen@npm:8.0.3" + dependencies: + "@babel/core": "npm:^7.28.0" + "@babel/traverse": "npm:^7.28.0" + "@babel/types": "npm:^7.28.2" + "@types/babel__core": "npm:^7.20.5" + "@types/babel__traverse": "npm:^7.20.7" + "@types/doctrine": "npm:^0.0.9" + "@types/resolve": "npm:^1.20.2" + doctrine: "npm:^3.0.0" + resolve: "npm:^1.22.1" + strip-indent: "npm:^4.0.0" + checksum: 10c0/0231fb9177bc7c633f3d1f228eebb0ee90a2f0feac50b1869ef70b0a3683b400d7875547a2d5168f2619b63d4cc29d7c45ae33d3f621fc67a7fa6790ac2049f6 + languageName: node + linkType: hard + +"react-dom@npm:^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0": + version: 19.2.7 + resolution: "react-dom@npm:19.2.7" + dependencies: + scheduler: "npm:^0.27.0" + peerDependencies: + react: ^19.2.7 + checksum: 10c0/970ff600f6e80d47d39e2f226f12f226173b3cba3382efc97c5f0cd663de9af38c7a4c11c213fb936094faeac83060d660247accaa96b752180d5b951b9cfecb + languageName: node + linkType: hard + "react-dom@npm:^19.2.5": version: 19.2.5 resolution: "react-dom@npm:19.2.5" @@ -5516,6 +7432,13 @@ __metadata: languageName: node linkType: hard +"react@npm:^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0": + version: 19.2.7 + resolution: "react@npm:19.2.7" + checksum: 10c0/0bd0e2f1bbd4ba97561c6597bf8a5fec05e6476fe61e165c1065598d16668efc6715205599c94d3ddd49d36cb0f21cbf1b9bcc18ee840b805ce222c3e8d558ac + languageName: node + linkType: hard + "react@npm:^19.2.5": version: 19.2.5 resolution: "react@npm:19.2.5" @@ -5544,6 +7467,19 @@ __metadata: languageName: node linkType: hard +"recast@npm:^0.23.5": + version: 0.23.11 + resolution: "recast@npm:0.23.11" + dependencies: + ast-types: "npm:^0.16.1" + esprima: "npm:~4.0.0" + source-map: "npm:~0.6.1" + tiny-invariant: "npm:^1.3.3" + tslib: "npm:^2.0.1" + checksum: 10c0/45b520a8f0868a5a24ecde495be9de3c48e69a54295d82a7331106554b75cfba75d16c909959d056e9ceed47a1be5e061e2db8b9ecbcd6ba44c2f3ef9a47bd18 + languageName: node + linkType: hard + "recharts@npm:^3.8.1": version: 3.8.1 resolution: "recharts@npm:3.8.1" @@ -5567,6 +7503,16 @@ __metadata: languageName: node linkType: hard +"redent@npm:^3.0.0": + version: 3.0.0 + resolution: "redent@npm:3.0.0" + dependencies: + indent-string: "npm:^4.0.0" + strip-indent: "npm:^3.0.0" + checksum: 10c0/d64a6b5c0b50eb3ddce3ab770f866658a2b9998c678f797919ceb1b586bab9259b311407280bd80b804e2a7c7539b19238ae6a2a20c843f1a7fcff21d48c2eae + languageName: node + linkType: hard + "redux-thunk@npm:^3.1.0": version: 3.1.0 resolution: "redux-thunk@npm:3.1.0" @@ -5645,6 +7591,20 @@ __metadata: languageName: node linkType: hard +"resolve@npm:^1.22.1, resolve@npm:^1.22.8": + version: 1.22.12 + resolution: "resolve@npm:1.22.12" + dependencies: + es-errors: "npm:^1.3.0" + is-core-module: "npm:^2.16.1" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/b16dc9b537c02e8c3388f7d3dcff9741d3071625f9a97ac1c885f2b0ca51e78df22328fb6d6ef214dd9101fb7cfc19aa2836fe3410402a94f3f7b8639c7149bf + languageName: node + linkType: hard + "resolve@patch:resolve@npm%3A^1.19.0#optional!builtin": version: 1.22.8 resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" @@ -5658,6 +7618,20 @@ __metadata: languageName: node linkType: hard +"resolve@patch:resolve@npm%3A^1.22.1#optional!builtin, resolve@patch:resolve@npm%3A^1.22.8#optional!builtin": + version: 1.22.12 + resolution: "resolve@patch:resolve@npm%3A1.22.12#optional!builtin::version=1.22.12&hash=c3c19d" + dependencies: + es-errors: "npm:^1.3.0" + is-core-module: "npm:^2.16.1" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/fc6519984ae1f894d877c0060ba8b1f5ba3bc0e85a02f74e141929c118c23d74d9735619a9cc2965397387e514884245c65d72a40731dcb6cfc84c7bcdc8321e + languageName: node + linkType: hard + "retry@npm:^0.12.0": version: 0.12.0 resolution: "retry@npm:0.12.0" @@ -5730,6 +7704,13 @@ __metadata: languageName: node linkType: hard +"run-applescript@npm:^7.0.0": + version: 7.1.0 + resolution: "run-applescript@npm:7.1.0" + checksum: 10c0/ab826c57c20f244b2ee807704b1ef4ba7f566aa766481ae5922aac785e2570809e297c69afcccc3593095b538a8a77d26f2b2e9a1d9dffee24e0e039502d1a03 + languageName: node + linkType: hard + "rxjs@npm:^7.8.2": version: 7.8.2 resolution: "rxjs@npm:7.8.2" @@ -5785,6 +7766,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^6.3.1": + version: 6.3.1 + resolution: "semver@npm:6.3.1" + bin: + semver: bin/semver.js + checksum: 10c0/e3d79b609071caa78bcb6ce2ad81c7966a46a7431d9d58b8800cfa9cb6a63699b3899a0e4bcce36167a284578212d9ae6942b6929ba4aa5015c079a67751d42d + languageName: node + linkType: hard + "semver@npm:^7.3.5": version: 7.6.3 resolution: "semver@npm:7.6.3" @@ -5794,6 +7784,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.7.3": + version: 7.8.4 + resolution: "semver@npm:7.8.4" + bin: + semver: bin/semver.js + checksum: 10c0/81b7c296fd7927b80f67fa516b75fa1017caac8167795320de28e76ccbc6f7f01763c30ecd10d6a0d8fd089708ab0548a5aebb94b0870e99c2a2b4600a46389b + languageName: node + linkType: hard + "set-cookie-parser@npm:^2.6.0": version: 2.7.2 resolution: "set-cookie-parser@npm:2.7.2" @@ -5936,6 +7935,42 @@ __metadata: languageName: node linkType: hard +"storybook@npm:^10.4.3": + version: 10.4.3 + resolution: "storybook@npm:10.4.3" + dependencies: + "@storybook/global": "npm:^5.0.0" + "@storybook/icons": "npm:^2.0.2" + "@testing-library/jest-dom": "npm:^6.9.1" + "@testing-library/user-event": "npm:^14.6.1" + "@vitest/expect": "npm:3.2.4" + "@vitest/spy": "npm:3.2.4" + "@webcontainer/env": "npm:^1.1.1" + esbuild: "npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.26.0 || ^0.27.0" + open: "npm:^10.2.0" + oxc-parser: "npm:^0.127.0" + oxc-resolver: "npm:^11.19.1" + recast: "npm:^0.23.5" + semver: "npm:^7.7.3" + use-sync-external-store: "npm:^1.5.0" + ws: "npm:^8.18.0" + peerDependencies: + "@types/react": ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + prettier: ^2 || ^3 + vite-plus: ^0.1.15 + peerDependenciesMeta: + "@types/react": + optional: true + prettier: + optional: true + vite-plus: + optional: true + bin: + storybook: ./dist/bin/dispatcher.js + checksum: 10c0/79eb863bca38983bd4dca04df57ae29a3650031bf8d0beed3507fbe4f87547313fcc066b7b0ec4d16b386109b7142898ed1b07f3ea807cc3babc7aa23b6f628e + languageName: node + linkType: hard + "string-convert@npm:^0.2.0": version: 0.2.1 resolution: "string-convert@npm:0.2.1" @@ -5992,6 +8027,29 @@ __metadata: languageName: node linkType: hard +"strip-bom@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-bom@npm:3.0.0" + checksum: 10c0/51201f50e021ef16672593d7434ca239441b7b760e905d9f33df6e4f3954ff54ec0e0a06f100d028af0982d6f25c35cd5cda2ce34eaebccd0250b8befb90d8f1 + languageName: node + linkType: hard + +"strip-indent@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-indent@npm:3.0.0" + dependencies: + min-indent: "npm:^1.0.0" + checksum: 10c0/ae0deaf41c8d1001c5d4fbe16cb553865c1863da4fae036683b474fa926af9fc121e155cb3fc57a68262b2ae7d5b8420aa752c97a6428c315d00efe2a3875679 + languageName: node + linkType: hard + +"strip-indent@npm:^4.0.0": + version: 4.1.1 + resolution: "strip-indent@npm:4.1.1" + checksum: 10c0/5b23dd5934be0ef6b6fe1b802887f83e56ad9dcd9f6c3896a637da2c6c3a6da3fdf3e51354a98e6cccb6f1c41863e7b9b9deaa348639dfd35f71f3549edb4dff + languageName: node + linkType: hard + "striptags@npm:^3.1.1": version: 3.2.0 resolution: "striptags@npm:3.2.0" @@ -6128,7 +8186,7 @@ __metadata: languageName: node linkType: hard -"tiny-invariant@npm:^1.3.3": +"tiny-invariant@npm:^1.3.1, tiny-invariant@npm:^1.3.3": version: 1.3.3 resolution: "tiny-invariant@npm:1.3.3" checksum: 10c0/65af4a07324b591a059b35269cd696aba21bef2107f29b9f5894d83cc143159a204b299553435b03874ebb5b94d019afa8b8eff241c8a4cfee95872c2e1c1c4a @@ -6162,6 +8220,20 @@ __metadata: languageName: node linkType: hard +"tinyrainbow@npm:^2.0.0": + version: 2.0.0 + resolution: "tinyrainbow@npm:2.0.0" + checksum: 10c0/c83c52bef4e0ae7fb8ec6a722f70b5b6fa8d8be1c85792e829f56c0e1be94ab70b293c032dc5048d4d37cfe678f1f5babb04bdc65fd123098800148ca989184f + languageName: node + linkType: hard + +"tinyspy@npm:^4.0.3": + version: 4.0.4 + resolution: "tinyspy@npm:4.0.4" + checksum: 10c0/a8020fc17799251e06a8398dcc352601d2770aa91c556b9531ecd7a12581161fd1c14e81cbdaff0c1306c93bfdde8ff6d1c1a3f9bbe6d91604f0fd4e01e2f1eb + languageName: node + linkType: hard + "to-fast-properties@npm:^2.0.0": version: 2.0.0 resolution: "to-fast-properties@npm:2.0.0" @@ -6200,6 +8272,24 @@ __metadata: languageName: node linkType: hard +"ts-dedent@npm:^2.0.0": + version: 2.3.0 + resolution: "ts-dedent@npm:2.3.0" + checksum: 10c0/bfc3331e0740191c0134fb526e7f01e16657e50955c9395de14703c6ef17119c91651fa044cf558dc9c1dbb0fe1b2a74e303aeebcbd5e3b31acd14f72f545a54 + languageName: node + linkType: hard + +"tsconfig-paths@npm:^4.2.0": + version: 4.2.0 + resolution: "tsconfig-paths@npm:4.2.0" + dependencies: + json5: "npm:^2.2.2" + minimist: "npm:^1.2.6" + strip-bom: "npm:^3.0.0" + checksum: 10c0/09a5877402d082bb1134930c10249edeebc0211f36150c35e1c542e5b91f1047b1ccf7da1e59babca1ef1f014c525510f4f870de7c9bda470c73bb4e2721b3ea + languageName: node + linkType: hard + "tslib@npm:^1.10.0": version: 1.14.1 resolution: "tslib@npm:1.14.1" @@ -6300,6 +8390,42 @@ __metadata: languageName: node linkType: hard +"unplugin@npm:^1.3.1": + version: 1.16.1 + resolution: "unplugin@npm:1.16.1" + dependencies: + acorn: "npm:^8.14.0" + webpack-virtual-modules: "npm:^0.6.2" + checksum: 10c0/dd5f8c5727d0135847da73cf03fb199107f1acf458167034886fda3405737dab871ad3926431b4f70e1e82cdac482ac1383cea4019d782a68515c8e3e611b6cc + languageName: node + linkType: hard + +"unplugin@npm:^2.3.5": + version: 2.3.11 + resolution: "unplugin@npm:2.3.11" + dependencies: + "@jridgewell/remapping": "npm:^2.3.5" + acorn: "npm:^8.15.0" + picomatch: "npm:^4.0.3" + webpack-virtual-modules: "npm:^0.6.2" + checksum: 10c0/273c1eab0eca4470c7317428689295c31dbe8ab0b306504de9f03cd20c156debb4131bef24b27ac615862958c5dd950a3951d26c0723ea774652ab3624149cff + languageName: node + linkType: hard + +"update-browserslist-db@npm:^1.2.3": + version: 1.2.3 + resolution: "update-browserslist-db@npm:1.2.3" + dependencies: + escalade: "npm:^3.2.0" + picocolors: "npm:^1.1.1" + peerDependencies: + browserslist: ">= 4.21.0" + bin: + update-browserslist-db: cli.js + checksum: 10c0/13a00355ea822388f68af57410ce3255941d5fb9b7c49342c4709a07c9f230bbef7f7499ae0ca7e0de532e79a82cc0c4edbd125f1a323a1845bf914efddf8bec + languageName: node + linkType: hard + "update-input-width@npm:^1.2.2": version: 1.4.2 resolution: "update-input-width@npm:1.4.2" @@ -6338,7 +8464,7 @@ __metadata: languageName: node linkType: hard -"use-sync-external-store@npm:^1.2.2, use-sync-external-store@npm:^1.4.0": +"use-sync-external-store@npm:^1.2.2, use-sync-external-store@npm:^1.4.0, use-sync-external-store@npm:^1.5.0": version: 1.6.0 resolution: "use-sync-external-store@npm:1.6.0" peerDependencies: @@ -6382,6 +8508,15 @@ __metadata: languageName: node linkType: hard +"uuid@npm:^9.0.0": + version: 9.0.1 + resolution: "uuid@npm:9.0.1" + bin: + uuid: dist/bin/uuid + checksum: 10c0/1607dd32ac7fc22f2d8f77051e6a64845c9bce5cd3dd8aa0070c074ec73e666a1f63c7b4e0f4bf2bc8b9d59dc85a15e17807446d9d2b17c8485fbc2147b27f9b + languageName: node + linkType: hard + "validate.io-array@npm:^1.0.3": version: 1.0.6 resolution: "validate.io-array@npm:1.0.6" @@ -6655,6 +8790,13 @@ __metadata: languageName: node linkType: hard +"webpack-virtual-modules@npm:^0.6.2": + version: 0.6.2 + resolution: "webpack-virtual-modules@npm:0.6.2" + checksum: 10c0/5ffbddf0e84bf1562ff86cf6fcf039c74edf09d78358a6904a09bbd4484e8bb6812dc385fe14330b715031892dcd8423f7a88278b57c9f5002c84c2860179add + languageName: node + linkType: hard + "whatwg-encoding@npm:^2.0.0": version: 2.0.0 resolution: "whatwg-encoding@npm:2.0.0" @@ -6766,6 +8908,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:^8.18.0": + version: 8.21.0 + resolution: "ws@npm:8.21.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10c0/ef4a243476283fc49bc7550966c4af4aa0eef56273837211e700de3b664e08604a760cdddcb5ba43c049140e74ccfec5b0ee0bb439e08c2adf9138902fdde5f9 + languageName: node + linkType: hard + "ws@npm:^8.2.3": version: 8.18.0 resolution: "ws@npm:8.18.0" @@ -6781,6 +8938,15 @@ __metadata: languageName: node linkType: hard +"wsl-utils@npm:^0.1.0": + version: 0.1.0 + resolution: "wsl-utils@npm:0.1.0" + dependencies: + is-wsl: "npm:^3.1.0" + checksum: 10c0/44318f3585eb97be994fc21a20ddab2649feaf1fbe893f1f866d936eea3d5f8c743bec6dc02e49fbdd3c0e69e9b36f449d90a0b165a4f47dd089747af4cf2377 + languageName: node + linkType: hard + "xml-name-validator@npm:^4.0.0": version: 4.0.0 resolution: "xml-name-validator@npm:4.0.0" @@ -6906,6 +9072,13 @@ __metadata: languageName: node linkType: hard +"yallist@npm:^3.0.2": + version: 3.1.1 + resolution: "yallist@npm:3.1.1" + checksum: 10c0/c66a5c46bc89af1625476f7f0f2ec3653c1a1791d2f9407cfb4c2ba812a1e1c9941416d71ba9719876530e3340a99925f697142989371b72d93b9ee628afd8c1 + languageName: node + linkType: hard + "yallist@npm:^4.0.0": version: 4.0.0 resolution: "yallist@npm:4.0.0" From 1eb48aba9c0b676ec93c71b216b630c981ed3287 Mon Sep 17 00:00:00 2001 From: yannis Date: Thu, 11 Jun 2026 16:30:03 +0300 Subject: [PATCH 03/16] refactor(client): move menu logic out of adminpage --- packages/client/app/Pages.jsx | 2 +- packages/client/app/Router.tsx | 23 +- packages/client/app/components/AdminPage.jsx | 916 +++++++----------- packages/client/app/components/Menu.jsx | 6 +- .../components/UserComponent.jsx | 12 +- .../xpub-with-context/src/index.jsx | 18 - .../xpub-with-context/src/index.tsx | 25 + packages/client/app/pages/Menu.page.tsx | 224 +++++ packages/client/app/pages/index.ts | 1 + 9 files changed, 645 insertions(+), 582 deletions(-) delete mode 100644 packages/client/app/components/xpub-with-context/src/index.jsx create mode 100644 packages/client/app/components/xpub-with-context/src/index.tsx create mode 100644 packages/client/app/pages/Menu.page.tsx diff --git a/packages/client/app/Pages.jsx b/packages/client/app/Pages.jsx index d61018661..6c2b3c54b 100644 --- a/packages/client/app/Pages.jsx +++ b/packages/client/app/Pages.jsx @@ -21,7 +21,7 @@ import AssetManager from './components/asset-manager/src/AssetManagerPage' import { JournalProvider } from './components/xpub-journal' import journal from '../config/journal' import ModalProvider from './components/asset-manager/src/ui/Modal/ModalProvider' -import { XpubProvider } from './components/xpub-with-context/src' +import { XpubProvider } from './components/xpub-with-context/src/index' import { reloadTranslationsForGroup } from './i18n' import Router from './Router' diff --git a/packages/client/app/Router.tsx b/packages/client/app/Router.tsx index 682c3094c..a3ef93c80 100644 --- a/packages/client/app/Router.tsx +++ b/packages/client/app/Router.tsx @@ -1,5 +1,5 @@ -import { type ReactNode } from 'react' -import { Route, Routes, Navigate } from 'react-router-dom' +import { type ReactNode, useContext } from 'react' +import { Route, Routes, Navigate, Outlet } from 'react-router-dom' import AcceptArticleOwnershipPage from './components/component-dashboard/src/components/AcceptArticleOwnershipPage' import ArticleArtifactPage from './components/component-published-artifact/components/ArticleArtifactPage' @@ -7,12 +7,17 @@ import DeclineArticleOwnershipPage from './components/component-dashboard/src/co import GroupPage from './components/component-frontpage/src/GroupPage' import InvitationAcceptedPage from './components/component-dashboard/src/components/InvitationAcceptedPage' import Login from './components/component-login/src' +import { XpubContext } from './components/xpub-with-context/src' -import { GroupWrapperPage } from './pages' +import { GroupWrapperPage, MenuPage } from './pages' + +import Layout from './ui/base/Layout' import AdminPage from './components/AdminPage' const Router = (): ReactNode => { + const [conversion] = useContext(XpubContext) + return ( } path="/" /> @@ -42,8 +47,16 @@ const Router = (): ReactNode => { path={`versions/:version/artifacts/:artifactId`} /> - {/* AdminPage has nested routes within */} - } path="*" /> + + + + + } + > + } path="*" /> + ) diff --git a/packages/client/app/components/AdminPage.jsx b/packages/client/app/components/AdminPage.jsx index c4849935d..bade4041c 100644 --- a/packages/client/app/components/AdminPage.jsx +++ b/packages/client/app/components/AdminPage.jsx @@ -1,23 +1,14 @@ /* eslint-disable react/prop-types, react-hooks/exhaustive-deps, react-hooks/immutability, react-hooks/refs */ -import { useApolloClient, useMutation, useQuery } from '@apollo/client/react' +import { useMutation, useQuery } from '@apollo/client/react' import PropTypes from 'prop-types' import { useContext, useEffect, useRef } from 'react' import Modal from 'react-modal' -import { - matchPath, - Navigate, - Route, - Routes, - useLocation, -} from 'react-router-dom' +import { Navigate, Route, Routes } from 'react-router-dom' import i18next from 'i18next' -import { useTranslation } from 'react-i18next' import { JournalContext } from './xpub-journal' -import { XpubContext } from './xpub-with-context/src' import { ConfigContext } from './config/src' import { getLanguages } from '../i18n' -import Layout from '../ui/base/Layout' import FormBuilderPage from './component-formbuilder/src/components/FormBuilderPage' import ManuscriptPage from './component-manuscript/src/components/ManuscriptPage' @@ -42,7 +33,6 @@ import CMSPublishingCollectionPage from './component-cms-manager/src/CMSPublishi import CMSFileBrowserPage from './component-cms-manager/src/CMSFileBrowserPage' import { CURRENT_USER, UPDATE_LANGUAGE } from '../queries' -import Menu from './Menu' import { Spinner, PageError } from './shared' import DashboardEditsPage from './component-dashboard/src/components/DashboardEditsPage' @@ -50,10 +40,6 @@ import DashboardLayout from './component-dashboard/src/components/DashboardLayou import DashboardReviewsPage from './component-dashboard/src/components/DashboardReviewsPage' import DashboardSubmissionsPage from './component-dashboard/src/components/DashboardSubmissionsPage' -const getParams = ({ routerPath, path }) => { - return matchPath(routerPath, path).params -} - // TODO: Redirect if token expires const PrivateRoute = ({ component: Component, @@ -89,14 +75,10 @@ PrivateRoute.propTypes = { const AdminPage = () => { Modal.setAppElement('#root') const journal = useContext(JournalContext) - const [conversion] = useContext(XpubContext) const config = useContext(ConfigContext) - const { urlFrag, instanceName } = config - const location = useLocation() - const { t } = useTranslation() - const client = useApolloClient() + const { urlFrag } = config - const { loading, error, data } = useQuery(CURRENT_USER, { + const { loading, data } = useQuery(CURRENT_USER, { fetchPolicy: 'network-only', pollInterval: 120000, }) @@ -126,186 +108,30 @@ const AdminPage = () => { return } - let notice = '' - - if (error || !data?.currentUser) { - if (error?.networkError) { - notice = 'You are offline.' - } else { - if (localStorage.getItem('token') !== null) { - localStorage.removeItem('token') - } - - client.cache.reset() - - localStorage.setItem('intendedPage', location.pathname + location.search) - const redirectlocation = `${urlFrag}/login` - return - } - } - const currentUser = data?.currentUser journal.textStyles = data?.builtCss?.css - const hasAlert = data?.userHasTaskAlerts previousDataRef.current = data - const showLinks = location.pathname.match(/^\/(submit|manuscript)/g) - let links = [] - const submissionFormBuilderLink = `${urlFrag}/admin/submission-form-builder` - const reviewFormBuilderLink = `${urlFrag}/admin/review-form-builder` - const decisionFormBuilderLink = `${urlFrag}/admin/decision-form-builder` - const configurationLink = `${urlFrag}/admin/configuration` const homeLink = `${urlFrag}/dashboard` const dashboardSubmissionsLink = `${urlFrag}/dashboard/submissions` const dashboardReviewsLink = `${urlFrag}/dashboard/reviews` const dashboardEditsLink = `${urlFrag}/dashboard/edits` - const profileLink = `${urlFrag}/profile` - const manuscriptsLink = `${urlFrag}/admin/manuscripts` const reportsLink = `${urlFrag}/admin/reports` - const userAdminLink = `${urlFrag}/admin/users` - const tasksTemplateLink = `${urlFrag}/admin/tasks` + const profileLink = `${urlFrag}/profile` const CMSPagesPageLink = `${urlFrag}/admin/cms/pages` const CMSLayoutPageLink = `${urlFrag}/admin/cms/layout` const CMSArticlePageLink = `${urlFrag}/admin/cms/article` const CMSFileBrowserLink = `${urlFrag}/admin/cms/filebrowser` const CMSMetadataPageLink = `${urlFrag}/admin/cms/metadata` const CMSPublishingCollectionPageLink = `${urlFrag}/admin/cms/collections` - const loginLink = `${urlFrag}/login?next=${homeLink}` - const path = `${urlFrag}/versions/:version` const redirectLink = `${urlFrag}/login?next=${homeLink}` - if (showLinks) { - const params = getParams(location.pathname, path) - const baseLink = `${urlFrag}/versions/${params.version}` - const submitLink = `${baseLink}/submit` - const manuscriptLink = `${baseLink}/manuscript` - - links = showLinks - ? [ - { link: submitLink, name: t('leftMenu.Summary Info') }, - { - link: manuscriptLink, - name: t('leftMenu.Manuscript'), - }, - ] - : null - } - const isUser = currentUser?.groupRoles?.includes('user') const isGroupManager = currentUser?.groupRoles?.includes('groupManager') const isGroupAdmin = currentUser?.groupRoles?.includes('groupAdmin') const isAdmin = currentUser?.globalRoles?.includes('admin') - if ( - currentUser && - (isUser || isGroupManager || isGroupAdmin || isAdmin) && - ['journal', 'prc', 'preprint2'].includes(instanceName) // TODO: remove instance based logic and refactor it to be enabled and disabled from config manager - ) { - links.push({ - link: homeLink, - name: t('leftMenu.Dashboard'), - icon: 'home', - hasAlert, - }) - } - - if (isGroupManager || isGroupAdmin) { - links.push({ - link: manuscriptsLink, - name: t('leftMenu.Manuscripts'), - icon: 'file-text', - }) - if (config?.report?.showInMenu && isGroupAdmin) - links.push({ - link: reportsLink, - name: t('leftMenu.Reports'), - icon: 'activity', - }) - } - - if (isGroupAdmin || isAdmin) { - links.push({ - menu: 'Settings', - name: t('leftMenu.Settings'), - icon: 'settings', - links: [ - { - menu: 'Forms', - name: t('leftMenu.Forms'), - icon: 'check-square', - links: [ - { - link: submissionFormBuilderLink, - name: t('leftMenu.Submission'), - }, - { - link: reviewFormBuilderLink, - name: t('leftMenu.Review'), - }, - { - link: decisionFormBuilderLink, - name: t('leftMenu.Decision'), - }, - ], - }, - { - link: tasksTemplateLink, - name: t('leftMenu.Tasks'), - icon: 'list', - }, - { - link: userAdminLink, - name: t('leftMenu.Users'), - icon: 'users', - }, - { - link: configurationLink, - name: t('leftMenu.Configuration'), - icon: 'sliders', - }, - { - menu: 'CMS', - name: t('leftMenu.CMS'), - icon: 'layout', - links: [ - { - link: CMSPagesPageLink, - name: t('leftMenu.Pages'), - icon: '', - }, - { - link: CMSLayoutPageLink, - name: t('leftMenu.Layout'), - icon: '', - }, - { - link: CMSArticlePageLink, - name: t('leftMenu.Article'), - icon: '', - }, - { - link: CMSMetadataPageLink, - name: t('leftMenu.Metadata'), - icon: '', - }, - { - link: CMSFileBrowserLink, - name: t('leftMenu.FileBrowser'), - - icon: '', - }, - { - link: CMSPublishingCollectionPageLink, - name: t('leftMenu.Collections'), - icon: '', - }, - ], - }, - ], - }) - } - const invitationId = window.localStorage.getItem('invitationId') ? window.localStorage.getItem('invitationId') : '' @@ -333,395 +159,383 @@ const AdminPage = () => { ) return ( - - + + } + path="profile" /> - + + {(isUser || isGroupManager || isGroupAdmin || isAdmin) && [ } - path="profile" - /> - - {(isUser || isGroupManager || isGroupAdmin || isAdmin) && [ - - } - key="profile" - path="profile/:id" - />, - - } - key="new-submission" - path="newSubmission" - />, - - } - key="review" - path="versions/:version/review" - />, - - } - key="review-preview" - path="versions/:version/reviewPreview" - />, - - } - key="decision" - path="versions/:version/decision" - />, - - } - key="submit" - path={`versions/:version/${ - ['preprint1', 'preprint2'].includes(config.instanceName) - ? 'evaluation' - : 'submit' - }`} // TODO: Remove instance based custom submit page and refactor it use config manager flag in future - />, - - + key="profile" + path="profile/:id" + />, + + } + key="new-submission" + path="newSubmission" + />, + + } + key="review" + path="versions/:version/review" + />, + + } + key="review-preview" + path="versions/:version/reviewPreview" + />, + + } + key="decision" + path="versions/:version/decision" + />, + + } + key="submit" + path={`versions/:version/${ + ['preprint1', 'preprint2'].includes(config.instanceName) + ? 'evaluation' + : 'submit' + }`} // TODO: Remove instance based custom submit page and refactor it use config manager flag in future + />, + + + + } + path="" + /> + {config?.dashboard?.showSections?.includes('submission') && ( } - path="" + key="submission" + path="submissions" /> - {config?.dashboard?.showSections?.includes('submission') && ( - - } - key="submission" - path="submissions" - /> - )} - {config?.dashboard?.showSections?.includes('review') && ( - - } - key="review" - path="reviews" - /> - )} - {config?.dashboard?.showSections?.includes('editor') && ( - - } - key="editor" - path="edits" - /> - )} - - - } - key="dashboard" - path={`dashboard/*`} - />, - - } - key="production" - path="versions/:version/production" - />, - ]} - {(isGroupAdmin || isAdmin) && [ - // We use array instead of <> because of https://stackoverflow.com/a/68637108/6505513 - - } - key="form-builder" - path={`/admin/form-builder`} - />, - - } - key="submission-form-builder" - path={`admin/submission-form-builder`} - />, - - } - key="review-form-builder" - path={`admin/review-form-builder`} - />, - - } - key="decision-form-builder" - path={`admin/decision-form-builder`} - />, - - } - key="users" - path={`admin/users`} - />, - - } - key="tasks" - path={`admin/tasks`} - />, - - } - key="CMSPagesPage" - path={`admin/cms/pages/:pageId?`} - />, - - } - key="CMSLayoutPage" - path="admin/cms/layout" - />, - - } - key="CMSArticlePage" - path="admin/cms/article" - />, - - } - key="CMSFileBrowserPage" - path="admin/cms/filebrowser" - />, - - } - key="CMSMetadataPage" - path="admin/cms/metadata" - />, - - } - key="CMSPublishingCollectionPage" - path="admin/cms/collections" - />, - - } - key="configuration" - path={`admin/configuration`} - />, - ]} - {(isGroupManager || isGroupAdmin) && [ - - } - key="manuscript" - path={`versions/:version/manuscript`} - />, - - } - key="manuscripts" - path={`admin/manuscripts`} - />, - ]} - {isGroupAdmin && [ - - } - key="reports" - path="admin/reports" - />, - ]} - - {isUser || isGroupManager || isGroupAdmin || isAdmin ? ( - } path="*" /> - ) : ( - } path="*" /> - )} - - + )} + {config?.dashboard?.showSections?.includes('review') && ( + + } + key="review" + path="reviews" + /> + )} + {config?.dashboard?.showSections?.includes('editor') && ( + + } + key="editor" + path="edits" + /> + )} + + + } + key="dashboard" + path={`dashboard/*`} + />, + + } + key="production" + path="versions/:version/production" + />, + ]} + {(isGroupAdmin || isAdmin) && [ + // We use array instead of <> because of https://stackoverflow.com/a/68637108/6505513 + + } + key="form-builder" + path={`/admin/form-builder`} + />, + + } + key="submission-form-builder" + path={`admin/submission-form-builder`} + />, + + } + key="review-form-builder" + path={`admin/review-form-builder`} + />, + + } + key="decision-form-builder" + path={`admin/decision-form-builder`} + />, + + } + key="users" + path={`admin/users`} + />, + + } + key="tasks" + path={`admin/tasks`} + />, + + } + key="CMSPagesPage" + path={`admin/cms/pages/:pageId?`} + />, + + } + key="CMSLayoutPage" + path="admin/cms/layout" + />, + + } + key="CMSArticlePage" + path="admin/cms/article" + />, + + } + key="CMSFileBrowserPage" + path="admin/cms/filebrowser" + />, + + } + key="CMSMetadataPage" + path="admin/cms/metadata" + />, + + } + key="CMSPublishingCollectionPage" + path="admin/cms/collections" + />, + + } + key="configuration" + path={`admin/configuration`} + />, + ]} + {(isGroupManager || isGroupAdmin) && [ + + } + key="manuscript" + path={`versions/:version/manuscript`} + />, + + } + key="manuscripts" + path={`admin/manuscripts`} + />, + ]} + {isGroupAdmin && [ + + } + key="reports" + path="admin/reports" + />, + ]} + + {isUser || isGroupManager || isGroupAdmin || isAdmin ? ( + } path="*" /> + ) : ( + } path="*" /> + )} + ) } diff --git a/packages/client/app/components/Menu.jsx b/packages/client/app/components/Menu.jsx index 84e8fdf94..7b35ef473 100644 --- a/packages/client/app/components/Menu.jsx +++ b/packages/client/app/components/Menu.jsx @@ -17,8 +17,7 @@ import { import { UPDATE_MENU } from '../queries' const Menu = ({ - className, - loginLink = '/login', + // loginLink = '/login', navLinkComponents, user, notice, @@ -74,7 +73,6 @@ const Menu = ({ return ( @@ -96,7 +94,7 @@ const Menu = ({ { +const UserComponent = ({ + user, + // loginLink, + profileLink, + t, + expanded, +}) => { return ( {user && ( @@ -35,7 +41,7 @@ const UserComponent = ({ user, loginLink, profileLink, t, expanded }) => { )} - {!user && } + {/* {!user && } */} ) } diff --git a/packages/client/app/components/xpub-with-context/src/index.jsx b/packages/client/app/components/xpub-with-context/src/index.jsx deleted file mode 100644 index 0d617e2f9..000000000 --- a/packages/client/app/components/xpub-with-context/src/index.jsx +++ /dev/null @@ -1,18 +0,0 @@ -/* eslint-disable react/prop-types */ - -import React, { useState } from 'react' - -const XpubContext = React.createContext([{ converting: false }, () => {}]) - -const XpubProvider = props => { - const { children } = props - const [state, setState] = useState({ converting: false }) - - return ( - - {children} - - ) -} - -export { XpubContext, XpubProvider } diff --git a/packages/client/app/components/xpub-with-context/src/index.tsx b/packages/client/app/components/xpub-with-context/src/index.tsx new file mode 100644 index 000000000..eb672ca56 --- /dev/null +++ b/packages/client/app/components/xpub-with-context/src/index.tsx @@ -0,0 +1,25 @@ +import React, { ReactNode, useState } from 'react' + +const XpubContext = React.createContext< + [ + { converting: boolean }, + React.Dispatch>, + ] +>([{ converting: false }, (): void => {}]) + +type Props = { + children: ReactNode +} + +const XpubProvider = (props: Props): ReactNode => { + const { children } = props + const [state, setState] = useState({ converting: false }) + + return ( + + {children} + + ) +} + +export { XpubContext, XpubProvider } diff --git a/packages/client/app/pages/Menu.page.tsx b/packages/client/app/pages/Menu.page.tsx new file mode 100644 index 000000000..aa8768558 --- /dev/null +++ b/packages/client/app/pages/Menu.page.tsx @@ -0,0 +1,224 @@ +import { type ReactNode, useContext } from 'react' +import { useTranslation } from 'react-i18next' +import { useLocation, useParams, Navigate } from 'react-router-dom' +import { useApolloClient, useQuery } from '@apollo/client/react' + +import { ConfigContext } from '../components/config/src' +import Menu from '../components/Menu' +import { CURRENT_USER } from '../queries' + +// const loginLink = `${urlFrag}/login?next=${homeLink}` + +type Link = { + name: string + + link?: string + icon?: string + hasAlert?: boolean + menu?: string + links?: Link[] +} + +const MenuPage = (): ReactNode => { + const location = useLocation() + const params = useParams() + const { t } = useTranslation() + const client = useApolloClient() + + const config = useContext(ConfigContext) + const { urlFrag, instanceName } = config + + // TO DO - this should be in a more generic place than the menu + const { loading, error, data } = useQuery(CURRENT_USER, { + fetchPolicy: 'network-only', + pollInterval: 120000, + }) + + if (loading) return null + + // @ts-ignore + const currentUser = data?.currentUser + + // @ts-ignore + const hasAlert = data?.userHasTaskAlerts + + let notice = '' + + // @ts-ignore + if (error || !data?.currentUser) { + // @ts-ignore + if (error?.networkError) { + notice = 'You are offline.' + } else { + if (localStorage.getItem('token') !== null) { + localStorage.removeItem('token') + } + + client.cache.reset() + + localStorage.setItem('intendedPage', location.pathname + location.search) + const redirectlocation = `${urlFrag}/login` + return + } + } + + const submissionFormBuilderLink = `${urlFrag}/admin/submission-form-builder` + const reviewFormBuilderLink = `${urlFrag}/admin/review-form-builder` + const decisionFormBuilderLink = `${urlFrag}/admin/decision-form-builder` + const configurationLink = `${urlFrag}/admin/configuration` + const manuscriptsLink = `${urlFrag}/admin/manuscripts` + const userAdminLink = `${urlFrag}/admin/users` + const tasksTemplateLink = `${urlFrag}/admin/tasks` + const CMSPagesPageLink = `${urlFrag}/admin/cms/pages` + const CMSLayoutPageLink = `${urlFrag}/admin/cms/layout` + const CMSArticlePageLink = `${urlFrag}/admin/cms/article` + const CMSFileBrowserLink = `${urlFrag}/admin/cms/filebrowser` + const CMSMetadataPageLink = `${urlFrag}/admin/cms/metadata` + const CMSPublishingCollectionPageLink = `${urlFrag}/admin/cms/collections` + const profileLink = `${urlFrag}/profile` + const reportsLink = `${urlFrag}/admin/reports` + const homeLink = `${urlFrag}/dashboard` + + const showLinks = location.pathname.match(/^\/(submit|manuscript)/g) + + const isUser = currentUser?.groupRoles?.includes('user') + const isGroupManager = currentUser?.groupRoles?.includes('groupManager') + const isGroupAdmin = currentUser?.groupRoles?.includes('groupAdmin') + const isAdmin = currentUser?.globalRoles?.includes('admin') + + let links: Link[] = [] + + if (showLinks) { + const baseLink = `${urlFrag}/versions/${params.version}` + const submitLink = `${baseLink}/submit` + const manuscriptLink = `${baseLink}/manuscript` + + links = [ + { link: submitLink, name: t('leftMenu.Summary Info') }, + { + link: manuscriptLink, + name: t('leftMenu.Manuscript'), + }, + ] + } + + if ( + currentUser && + (isUser || isGroupManager || isGroupAdmin || isAdmin) && + ['journal', 'prc', 'preprint2'].includes(instanceName) // TODO: remove instance based logic and refactor it to be enabled and disabled from config manager + ) { + links.push({ + link: homeLink, + name: t('leftMenu.Dashboard'), + icon: 'home', + hasAlert, + }) + } + + if (isGroupManager || isGroupAdmin) { + links.push({ + link: manuscriptsLink, + name: t('leftMenu.Manuscripts'), + icon: 'file-text', + }) + if (config?.report?.showInMenu && isGroupAdmin) + links.push({ + link: reportsLink, + name: t('leftMenu.Reports'), + icon: 'activity', + }) + } + + if (isGroupAdmin || isAdmin) { + links.push({ + menu: 'Settings', + name: t('leftMenu.Settings'), + icon: 'settings', + links: [ + { + menu: 'Forms', + name: t('leftMenu.Forms'), + icon: 'check-square', + links: [ + { + link: submissionFormBuilderLink, + name: t('leftMenu.Submission'), + }, + { + link: reviewFormBuilderLink, + name: t('leftMenu.Review'), + }, + { + link: decisionFormBuilderLink, + name: t('leftMenu.Decision'), + }, + ], + }, + { + link: tasksTemplateLink, + name: t('leftMenu.Tasks'), + icon: 'list', + }, + { + link: userAdminLink, + name: t('leftMenu.Users'), + icon: 'users', + }, + { + link: configurationLink, + name: t('leftMenu.Configuration'), + icon: 'sliders', + }, + { + menu: 'CMS', + name: t('leftMenu.CMS'), + icon: 'layout', + links: [ + { + link: CMSPagesPageLink, + name: t('leftMenu.Pages'), + icon: '', + }, + { + link: CMSLayoutPageLink, + name: t('leftMenu.Layout'), + icon: '', + }, + { + link: CMSArticlePageLink, + name: t('leftMenu.Article'), + icon: '', + }, + { + link: CMSMetadataPageLink, + name: t('leftMenu.Metadata'), + icon: '', + }, + { + link: CMSFileBrowserLink, + name: t('leftMenu.FileBrowser'), + + icon: '', + }, + { + link: CMSPublishingCollectionPageLink, + name: t('leftMenu.Collections'), + icon: '', + }, + ], + }, + ], + }) + } + + return ( + + ) +} + +export default MenuPage diff --git a/packages/client/app/pages/index.ts b/packages/client/app/pages/index.ts index e1d7e06e1..1df1e9e2f 100644 --- a/packages/client/app/pages/index.ts +++ b/packages/client/app/pages/index.ts @@ -1 +1,2 @@ export { default as GroupWrapperPage } from './GroupWrapper.page' +export { default as MenuPage } from './Menu.page' From d06cdc2e5717b9867f3800d695cc884f6cfae768 Mon Sep 17 00:00:00 2001 From: yannis Date: Mon, 15 Jun 2026 10:04:12 +0300 Subject: [PATCH 04/16] refactor(client): move all routes into router --- packages/client/app/Pages.jsx | 2 + packages/client/app/Router.tsx | 259 ++++++++- packages/client/app/components/AdminPage.jsx | 496 +----------------- .../src/components/DashboardEditsPage.jsx | 7 +- .../src/components/DashboardLayout.jsx | 9 +- .../src/components/DashboardRedirect.tsx | 39 ++ .../src/components/DashboardReviewsPage.jsx | 7 +- .../components/DashboardSubmissionsPage.jsx | 8 +- .../src/components/ManuscriptPage.jsx | 12 +- .../src/ManuscriptsPage.jsx | 7 +- .../src/components/ProductionPage.jsx | 7 +- .../component-profile/src/ProfilePage.jsx | 11 +- .../src/components/DecisionPage.jsx | 8 +- .../src/components/ReviewPage.jsx | 7 +- .../src/components/ReviewPreviewPage.jsx | 9 +- .../src/components/NewSubmissionPage.jsx | 10 +- .../src/components/SubmitPage.jsx | 8 +- .../src/components/SubmitRedirect.tsx | 28 + .../component-users-manager/src/UsersPage.jsx | 8 +- 19 files changed, 402 insertions(+), 540 deletions(-) create mode 100644 packages/client/app/components/component-dashboard/src/components/DashboardRedirect.tsx create mode 100644 packages/client/app/components/component-submit/src/components/SubmitRedirect.tsx diff --git a/packages/client/app/Pages.jsx b/packages/client/app/Pages.jsx index 6c2b3c54b..5cc3e7786 100644 --- a/packages/client/app/Pages.jsx +++ b/packages/client/app/Pages.jsx @@ -4,6 +4,7 @@ import { useEffect } from 'react' import { useLocation } from 'react-router-dom' import styled from 'styled-components' import { useQuery } from '@apollo/client/react' +import Modal from 'react-modal' import { grid } from '@coko/client' @@ -52,6 +53,7 @@ const modals = { } const Pages = () => { + Modal.setAppElement('#root') const location = useLocation() const { loading, error, data } = useQuery(GET_GROUPS) diff --git a/packages/client/app/Router.tsx b/packages/client/app/Router.tsx index a3ef93c80..5d9f4d66f 100644 --- a/packages/client/app/Router.tsx +++ b/packages/client/app/Router.tsx @@ -1,22 +1,122 @@ import { type ReactNode, useContext } from 'react' -import { Route, Routes, Navigate, Outlet } from 'react-router-dom' +import { Route, Routes, Navigate, Outlet, useParams } from 'react-router-dom' +import { useQuery } from '@apollo/client/react' import AcceptArticleOwnershipPage from './components/component-dashboard/src/components/AcceptArticleOwnershipPage' import ArticleArtifactPage from './components/component-published-artifact/components/ArticleArtifactPage' +import CMSArticlePage from './components/component-cms-manager/src/CMSArticlePage' +import CMSFileBrowserPage from './components/component-cms-manager/src/CMSFileBrowserPage' +import CMSLayoutPage from './components/component-cms-manager/src/CMSLayoutPage' +import CMSMetadataPage from './components/component-cms-manager/src/CMSMetadataPage' +import CMSPagesPage from './components/component-cms-manager/src/CMSPagesPage' +import CMSPublishingCollectionPage from './components/component-cms-manager/src/CMSPublishingCollectionPage' +import ConfigManagerPage from './components/component-config-manager/src/ConfigManagerPage' +import DashboardEditsPage from './components/component-dashboard/src/components/DashboardEditsPage' +import DashboardLayout from './components/component-dashboard/src/components/DashboardLayout' +import DashboardRedirect from './components/component-dashboard/src/components/DashboardRedirect' +import DashboardReviewsPage from './components/component-dashboard/src/components/DashboardReviewsPage' +import DashboardSubmissionsPage from './components/component-dashboard/src/components/DashboardSubmissionsPage' +import DecisionPage from './components/component-review/src/components/DecisionPage' import DeclineArticleOwnershipPage from './components/component-dashboard/src/components/DeclineArticleOwnershipPage' +import FormBuilderPage from './components/component-formbuilder/src/components/FormBuilderPage' import GroupPage from './components/component-frontpage/src/GroupPage' import InvitationAcceptedPage from './components/component-dashboard/src/components/InvitationAcceptedPage' import Login from './components/component-login/src' +import ManuscriptPage from './components/component-manuscript/src/components/ManuscriptPage' +import ManuscriptsPage from './components/component-manuscripts/src/ManuscriptsPage' +import NewSubmissionPage from './components/component-submit/src/components/NewSubmissionPage' +import { PageError } from './components/shared' +import ProductionPage from './components/component-production/src/components/ProductionPage' +import ProfilePage from './components/component-profile/src/ProfilePage' +import ReportPage from './components/component-reporting/src/ReportPage' +import ReviewPage from './components/component-review/src/components/ReviewPage' +import ReviewPreviewPage from './components/component-review/src/components/ReviewPreviewPage' +import SubmitRedirect from './components/component-submit/src/components/SubmitRedirect' +import TasksTemplatePage from './components/component-task-manager/src/TasksTemplatePage' +import UsersPage from './components/component-users-manager/src/UsersPage' + +import { ConfigContext } from './components/config/src' import { XpubContext } from './components/xpub-with-context/src' import { GroupWrapperPage, MenuPage } from './pages' +import { CURRENT_USER } from './queries' + import Layout from './ui/base/Layout' -import AdminPage from './components/AdminPage' +// #region helpers +const Authenticated = (): ReactNode => { + const { groupName } = useParams() + + // if ( + // ['journal', 'prc'].includes(instanceName) && + // currentUser && + // !currentUser.email && + // path !== `${urlFrag}/profile` // TODO configure this url via config manager + // ) { + // return + // } + + if (!localStorage.getItem('token')) { + return + } + + return +} + +enum Role { + // global + Admin = 'admin', + // group + User = 'user', + GroupManager = 'groupManager', + GroupAdmin = 'groupAdmin', +} + +type RoleGateProps = { + roles: Role[] +} + +const RoleGate = (props: RoleGateProps): ReactNode => { + const { roles } = props + + // switch to useCurrentUser once that has been wired up + const { data, loading, error } = useQuery(CURRENT_USER) + + if (error) { + // TO DO - handle this with ui + console.error(error) + return null + } + + if (loading) { + // TO DO - handle this with a spinner (or useCurrentUser should) + return null + } + + // @ts-ignore + const currentUser = data.currentUser + + const pass = roles.some(role => { + if (role === Role.Admin) { + return currentUser.globalRoles.includes(role) + } + + return currentUser.groupRoles.includes(role) + }) + + if (!pass) { + return + } + + return +} +// #endregion helpers const Router = (): ReactNode => { + // TO DO - look into how to get rid of these two const [conversion] = useContext(XpubContext) + const config = useContext(ConfigContext) return ( @@ -42,22 +142,157 @@ const Router = (): ReactNode => { path="invitation/accepted" /> + {/* TO DO - should this be public? */} } - path={`versions/:version/artifacts/:artifactId`} + path="versions/:version/artifacts/:artifactId" /> - - - - - } - > - } path="*" /> + }> + + + + + } + > + }> + } path="profile/:id" /> + + + }> + } path="profile" /> + } path="newSubmission" /> + } path="versions/:version/review" /> + + } + path="versions/:version/reviewPreview" + /> + + } + path="versions/:version/decision" + /> + + } + path="versions/:version/submit" + /> + + } + path="versions/:version/evaluation" + /> + + } + path="versions/:version/production" + /> + + + + } path="" /> + + {config?.dashboard?.showSections?.includes( + 'submission', + ) && ( + } + path="submissions" + /> + )} + + {config?.dashboard?.showSections?.includes('review') && ( + } + path="reviews" + /> + )} + + {config?.dashboard?.showSections?.includes('editor') && ( + } path="edits" /> + )} + + + } + path="dashboard/*" + /> + + + + } + > + } path="reports" /> + + } + path="submission-form-builder" + /> + + } + path="review-form-builder" + /> + + } + path="decision-form-builder" + /> + + } path="users" /> + } path="tasks" /> + + + } path="pages/:pageId?" /> + } path="layout" /> + } path="article" /> + } path="filebrowser" /> + } path="metadata" /> + } + path="collections" + /> + + + } path="configuration" /> + + + + } + > + } path="manuscripts" />, + + + + + } + > + } + key="manuscript" + path={`versions/:version/manuscript`} + /> + + + + } path="*" /> ) } diff --git a/packages/client/app/components/AdminPage.jsx b/packages/client/app/components/AdminPage.jsx index bade4041c..2a6d40f58 100644 --- a/packages/client/app/components/AdminPage.jsx +++ b/packages/client/app/components/AdminPage.jsx @@ -1,82 +1,19 @@ -/* eslint-disable react/prop-types, react-hooks/exhaustive-deps, react-hooks/immutability, react-hooks/refs */ +/* eslint-disable react-hooks/exhaustive-deps, react-hooks/immutability, react-hooks/refs */ import { useMutation, useQuery } from '@apollo/client/react' -import PropTypes from 'prop-types' + import { useContext, useEffect, useRef } from 'react' -import Modal from 'react-modal' -import { Navigate, Route, Routes } from 'react-router-dom' import i18next from 'i18next' import { JournalContext } from './xpub-journal' -import { ConfigContext } from './config/src' -import { getLanguages } from '../i18n' -import FormBuilderPage from './component-formbuilder/src/components/FormBuilderPage' -import ManuscriptPage from './component-manuscript/src/components/ManuscriptPage' -import ManuscriptsPage from './component-manuscripts/src/ManuscriptsPage' -import ProductionPage from './component-production/src/components/ProductionPage' -import ProfilePage from './component-profile/src/ProfilePage' -import ReportPage from './component-reporting/src/ReportPage' -import DecisionPage from './component-review/src/components/DecisionPage' -import ReviewPage from './component-review/src/components/ReviewPage' -import ReviewPreviewPage from './component-review/src/components/ReviewPreviewPage' -import NewSubmissionPage from './component-submit/src/components/NewSubmissionPage' -import SubmitPage from './component-submit/src/components/SubmitPage' -import TasksTemplatePage from './component-task-manager/src/TasksTemplatePage' -import UsersPage from './component-users-manager/src/UsersPage' -import ConfigManagerPage from './component-config-manager/src/ConfigManagerPage' +import { getLanguages } from '../i18n' -import CMSPagesPage from './component-cms-manager/src/CMSPagesPage' -import CMSLayoutPage from './component-cms-manager/src/CMSLayoutPage' -import CMSArticlePage from './component-cms-manager/src/CMSArticlePage' -import CMSMetadataPage from './component-cms-manager/src/CMSMetadataPage' -import CMSPublishingCollectionPage from './component-cms-manager/src/CMSPublishingCollectionPage' -import CMSFileBrowserPage from './component-cms-manager/src/CMSFileBrowserPage' import { CURRENT_USER, UPDATE_LANGUAGE } from '../queries' -import { Spinner, PageError } from './shared' - -import DashboardEditsPage from './component-dashboard/src/components/DashboardEditsPage' -import DashboardLayout from './component-dashboard/src/components/DashboardLayout' -import DashboardReviewsPage from './component-dashboard/src/components/DashboardReviewsPage' -import DashboardSubmissionsPage from './component-dashboard/src/components/DashboardSubmissionsPage' - -// TODO: Redirect if token expires -const PrivateRoute = ({ - component: Component, - redirectLink, - path, - currentUser, - ...rest -}) => { - const config = useContext(ConfigContext) - const { urlFrag, instanceName } = config - - if ( - ['journal', 'prc'].includes(instanceName) && - currentUser && - !currentUser.email && - path !== `${urlFrag}/profile` // TODO configure this url via config manager - ) { - return - } - - return localStorage.getItem('token') ? ( - - ) : ( - - ) -} - -PrivateRoute.propTypes = { - component: PropTypes.func.isRequired, - redirectLink: PropTypes.string.isRequired, -} +import { Spinner } from './shared' const AdminPage = () => { - Modal.setAppElement('#root') const journal = useContext(JournalContext) - const config = useContext(ConfigContext) - const { urlFrag } = config const { loading, data } = useQuery(CURRENT_USER, { fetchPolicy: 'network-only', @@ -113,430 +50,7 @@ const AdminPage = () => { previousDataRef.current = data - const homeLink = `${urlFrag}/dashboard` - const dashboardSubmissionsLink = `${urlFrag}/dashboard/submissions` - const dashboardReviewsLink = `${urlFrag}/dashboard/reviews` - const dashboardEditsLink = `${urlFrag}/dashboard/edits` - const reportsLink = `${urlFrag}/admin/reports` - const profileLink = `${urlFrag}/profile` - const CMSPagesPageLink = `${urlFrag}/admin/cms/pages` - const CMSLayoutPageLink = `${urlFrag}/admin/cms/layout` - const CMSArticlePageLink = `${urlFrag}/admin/cms/article` - const CMSFileBrowserLink = `${urlFrag}/admin/cms/filebrowser` - const CMSMetadataPageLink = `${urlFrag}/admin/cms/metadata` - const CMSPublishingCollectionPageLink = `${urlFrag}/admin/cms/collections` - const redirectLink = `${urlFrag}/login?next=${homeLink}` - - const isUser = currentUser?.groupRoles?.includes('user') - const isGroupManager = currentUser?.groupRoles?.includes('groupManager') - const isGroupAdmin = currentUser?.groupRoles?.includes('groupAdmin') - const isAdmin = currentUser?.globalRoles?.includes('admin') - - const invitationId = window.localStorage.getItem('invitationId') - ? window.localStorage.getItem('invitationId') - : '' - - const inviteAction = window.localStorage.getItem('inviteAction') - ? window.localStorage.getItem('inviteAction') - : '' - - const dashboardRedirectUrl = currentUser?.recentTab - ? `${urlFrag}/dashboard/${currentUser.recentTab}` - : dashboardSubmissionsLink - - const dashboardRedirect = () => - invitationId ? ( - - ) : ( - - ) - - return ( - - - } - path="profile" - /> - - {(isUser || isGroupManager || isGroupAdmin || isAdmin) && [ - - } - key="profile" - path="profile/:id" - />, - - } - key="new-submission" - path="newSubmission" - />, - - } - key="review" - path="versions/:version/review" - />, - - } - key="review-preview" - path="versions/:version/reviewPreview" - />, - - } - key="decision" - path="versions/:version/decision" - />, - - } - key="submit" - path={`versions/:version/${ - ['preprint1', 'preprint2'].includes(config.instanceName) - ? 'evaluation' - : 'submit' - }`} // TODO: Remove instance based custom submit page and refactor it use config manager flag in future - />, - - - - } - path="" - /> - {config?.dashboard?.showSections?.includes('submission') && ( - - } - key="submission" - path="submissions" - /> - )} - {config?.dashboard?.showSections?.includes('review') && ( - - } - key="review" - path="reviews" - /> - )} - {config?.dashboard?.showSections?.includes('editor') && ( - - } - key="editor" - path="edits" - /> - )} - - - } - key="dashboard" - path={`dashboard/*`} - />, - - } - key="production" - path="versions/:version/production" - />, - ]} - {(isGroupAdmin || isAdmin) && [ - // We use array instead of <> because of https://stackoverflow.com/a/68637108/6505513 - - } - key="form-builder" - path={`/admin/form-builder`} - />, - - } - key="submission-form-builder" - path={`admin/submission-form-builder`} - />, - - } - key="review-form-builder" - path={`admin/review-form-builder`} - />, - - } - key="decision-form-builder" - path={`admin/decision-form-builder`} - />, - - } - key="users" - path={`admin/users`} - />, - - } - key="tasks" - path={`admin/tasks`} - />, - - } - key="CMSPagesPage" - path={`admin/cms/pages/:pageId?`} - />, - - } - key="CMSLayoutPage" - path="admin/cms/layout" - />, - - } - key="CMSArticlePage" - path="admin/cms/article" - />, - - } - key="CMSFileBrowserPage" - path="admin/cms/filebrowser" - />, - - } - key="CMSMetadataPage" - path="admin/cms/metadata" - />, - - } - key="CMSPublishingCollectionPage" - path="admin/cms/collections" - />, - - } - key="configuration" - path={`admin/configuration`} - />, - ]} - {(isGroupManager || isGroupAdmin) && [ - - } - key="manuscript" - path={`versions/:version/manuscript`} - />, - - } - key="manuscripts" - path={`admin/manuscripts`} - />, - ]} - {isGroupAdmin && [ - - } - key="reports" - path="admin/reports" - />, - ]} - - {isUser || isGroupManager || isGroupAdmin || isAdmin ? ( - } path="*" /> - ) : ( - } path="*" /> - )} - - ) + return null } export default AdminPage diff --git a/packages/client/app/components/component-dashboard/src/components/DashboardEditsPage.jsx b/packages/client/app/components/component-dashboard/src/components/DashboardEditsPage.jsx index 3fdb8573c..5ad192169 100644 --- a/packages/client/app/components/component-dashboard/src/components/DashboardEditsPage.jsx +++ b/packages/client/app/components/component-dashboard/src/components/DashboardEditsPage.jsx @@ -1,5 +1,4 @@ /* eslint-disable react-hooks/exhaustive-deps */ -/* eslint-disable react/prop-types */ import { useMutation, useQuery } from '@apollo/client/react' import { useEffect, useContext } from 'react' @@ -16,15 +15,19 @@ import { REMOVE_TASK_ALERTS_FOR_CURRENT_USER, DASHBOARD, UPDATE_MANUSCRIPT, + CURRENT_USER, } from '../../../../queries' import EditorTable from './sections/EditorTable' import { CommsErrorBanner, Spinner } from '../../../shared' -const DashboardEditsPage = ({ currentUser }) => { +const DashboardEditsPage = () => { const location = useLocation() const config = useContext(ConfigContext) const wantedRoles = ['seniorEditor', 'handlingEditor', 'editor'] + const { data: currentUserData } = useQuery(CURRENT_USER) + const currentUser = currentUserData.currentUser + const applyQueryParams = useQueryParams() const uriQueryParams = new URLSearchParams(location.search) diff --git a/packages/client/app/components/component-dashboard/src/components/DashboardLayout.jsx b/packages/client/app/components/component-dashboard/src/components/DashboardLayout.jsx index a55e025bd..ee63cecb3 100644 --- a/packages/client/app/components/component-dashboard/src/components/DashboardLayout.jsx +++ b/packages/client/app/components/component-dashboard/src/components/DashboardLayout.jsx @@ -2,7 +2,7 @@ import { useContext } from 'react' import { th, grid } from '@coko/client' -import { Link, useLocation, useNavigate } from 'react-router-dom' +import { Link, useLocation, useParams, useNavigate } from 'react-router-dom' import styled from 'styled-components' import { useTranslation } from 'react-i18next' @@ -35,10 +35,11 @@ const Tabs = styled.div` margin-top: ${grid(1)}; ` -const DashboardLayout = ({ urlFrag, children }) => { +const DashboardLayout = ({ children }) => { const config = useContext(ConfigContext) const navigate = useNavigate() const location = useLocation() + const { groupName } = useParams() const applyQueryParams = useQueryParams() const uriQueryParams = new URLSearchParams(location.search) @@ -82,7 +83,7 @@ const DashboardLayout = ({ urlFrag, children }) => { /> @@ -95,7 +96,7 @@ const DashboardLayout = ({ urlFrag, children }) => { {dashboardPages.map(({ href, label }) => ( - +
{label}
diff --git a/packages/client/app/components/component-dashboard/src/components/DashboardRedirect.tsx b/packages/client/app/components/component-dashboard/src/components/DashboardRedirect.tsx new file mode 100644 index 000000000..811e7edd4 --- /dev/null +++ b/packages/client/app/components/component-dashboard/src/components/DashboardRedirect.tsx @@ -0,0 +1,39 @@ +import { type ReactNode } from 'react' +import { useParams, Navigate } from 'react-router-dom' +import { useQuery } from '@apollo/client/react' + +import { CURRENT_USER } from '../../../../queries' + +const DashboardRedirect = (): ReactNode => { + const { groupName } = useParams() + + const { data: currentUserData } = useQuery(CURRENT_USER) + // @ts-ignore + const currentUser = currentUserData.currentUser + + const invitationId = window.localStorage.getItem('invitationId') || '' + const inviteAction = window.localStorage.getItem('inviteAction') || '' + + const dashboardSubmissionsLink = `/${groupName}/dashboard/submissions` + + const dashboardRedirectUrl = currentUser?.recentTab + ? `/${groupName}/dashboard/${currentUser.recentTab}` + : dashboardSubmissionsLink + + if (invitationId) { + return ( + + ) + } + + return +} + +export default DashboardRedirect diff --git a/packages/client/app/components/component-dashboard/src/components/DashboardReviewsPage.jsx b/packages/client/app/components/component-dashboard/src/components/DashboardReviewsPage.jsx index 2910fa9bc..0739f3804 100644 --- a/packages/client/app/components/component-dashboard/src/components/DashboardReviewsPage.jsx +++ b/packages/client/app/components/component-dashboard/src/components/DashboardReviewsPage.jsx @@ -1,5 +1,4 @@ /* eslint-disable react-hooks/exhaustive-deps */ -/* eslint-disable react/prop-types */ import { useMutation, useQuery } from '@apollo/client/react' import { useEffect, useContext } from 'react' @@ -11,6 +10,7 @@ import { UPDATE_TAB, DASHBOARD, UPDATE_MANUSCRIPT, + CURRENT_USER, } from '../../../../queries' import { extractFilters, @@ -22,10 +22,13 @@ import { import ReviewerTable from './sections/ReviewerTable' import { CommsErrorBanner, Spinner } from '../../../shared' -const DashboardReviewsPage = ({ currentUser }) => { +const DashboardReviewsPage = () => { const location = useLocation() const config = useContext(ConfigContext) + const { data: currentUserData } = useQuery(CURRENT_USER) + const currentUser = currentUserData.currentUser + const wantedRoles = [ 'reviewer', 'invited:reviewer', diff --git a/packages/client/app/components/component-dashboard/src/components/DashboardSubmissionsPage.jsx b/packages/client/app/components/component-dashboard/src/components/DashboardSubmissionsPage.jsx index aac4314fd..688890e38 100644 --- a/packages/client/app/components/component-dashboard/src/components/DashboardSubmissionsPage.jsx +++ b/packages/client/app/components/component-dashboard/src/components/DashboardSubmissionsPage.jsx @@ -1,5 +1,4 @@ /* eslint-disable react-hooks/exhaustive-deps */ -/* eslint-disable react/prop-types */ import { useMutation, useQuery } from '@apollo/client/react' import { useEffect, useContext } from 'react' @@ -11,15 +10,18 @@ import { URI_PAGENUM_PARAM, useQueryParams, } from '../../../../shared/urlParamUtils' -import { UPDATE_TAB, DASHBOARD } from '../../../../queries' +import { CURRENT_USER, UPDATE_TAB, DASHBOARD } from '../../../../queries' import SubmissionsTable from './sections/SubmissionsTable' import { CommsErrorBanner, Spinner } from '../../../shared' -const DashboardSubmissionsPage = ({ currentUser }) => { +const DashboardSubmissionsPage = () => { const location = useLocation() const config = useContext(ConfigContext) const wantedRoles = ['author'] + const { data: currentUserData } = useQuery(CURRENT_USER) + const currentUser = currentUserData.currentUser + const applyQueryParams = useQueryParams() const uriQueryParams = new URLSearchParams(location.search) diff --git a/packages/client/app/components/component-manuscript/src/components/ManuscriptPage.jsx b/packages/client/app/components/component-manuscript/src/components/ManuscriptPage.jsx index 9bb191455..079cfc281 100644 --- a/packages/client/app/components/component-manuscript/src/components/ManuscriptPage.jsx +++ b/packages/client/app/components/component-manuscript/src/components/ManuscriptPage.jsx @@ -1,12 +1,13 @@ -/* eslint-disable react/prop-types */ - import { useParams } from 'react-router-dom' import { useQuery } from '@apollo/client/react' import Manuscript from './Manuscript' import { Spinner, CommsErrorBanner } from '../../../shared' -import { MANUSCRIPT_FOR_MANUSCRIPT_PAGE } from '../../../../queries' +import { + MANUSCRIPT_FOR_MANUSCRIPT_PAGE, + CURRENT_USER, +} from '../../../../queries' -const ManuscriptPage = ({ currentUser }) => { +const ManuscriptPage = () => { const params = useParams() const { data, loading, error } = useQuery(MANUSCRIPT_FOR_MANUSCRIPT_PAGE, { variables: { @@ -14,6 +15,9 @@ const ManuscriptPage = ({ currentUser }) => { }, }) + const { data: currentUserData } = useQuery(CURRENT_USER) + const currentUser = currentUserData.currentUser + if (loading) return if (error) return const { manuscript } = data diff --git a/packages/client/app/components/component-manuscripts/src/ManuscriptsPage.jsx b/packages/client/app/components/component-manuscripts/src/ManuscriptsPage.jsx index d59d95282..1db210c10 100644 --- a/packages/client/app/components/component-manuscripts/src/ManuscriptsPage.jsx +++ b/packages/client/app/components/component-manuscripts/src/ManuscriptsPage.jsx @@ -1,5 +1,4 @@ /* eslint-disable react-hooks/immutability */ -/* eslint-disable react/prop-types */ /* eslint-disable no-shadow */ @@ -30,6 +29,7 @@ import { PUBLISH_MANUSCRIPT, EXPAND_CHAT, UPDATE_MANUSCRIPT, + CURRENT_USER, } from '../../../queries' import Manuscripts from './Manuscripts' import { @@ -42,7 +42,7 @@ import { import { validateDoi, validateSuffix } from '../../../shared/commsUtils' import useChat from '../../../hooks/useChat' -const ManuscriptsPage = ({ currentUser }) => { +const ManuscriptsPage = () => { const location = useLocation() const { t } = useTranslation() const [doUpdateManuscript] = useMutation(UPDATE_MANUSCRIPT) @@ -50,6 +50,9 @@ const ManuscriptsPage = ({ currentUser }) => { const { urlFrag } = config const chatRoomId = fnv.hash(config.clientUrl).hex() + const { data: currentUserData } = useQuery(CURRENT_USER) + const currentUser = currentUserData.currentUser + /** Returns an array of column names, e.g. * ['shortId', 'created', 'titleAndAbstract', 'submission.topic', 'status'] */ const configuredColumnNames = (config?.manuscript?.tableColumns || '') diff --git a/packages/client/app/components/component-production/src/components/ProductionPage.jsx b/packages/client/app/components/component-production/src/components/ProductionPage.jsx index 48681f8f2..efea40fcd 100644 --- a/packages/client/app/components/component-production/src/components/ProductionPage.jsx +++ b/packages/client/app/components/component-production/src/components/ProductionPage.jsx @@ -1,4 +1,3 @@ -/* eslint-disable react/prop-types */ /* eslint-disable promise/catch-or-return, promise/always-return */ import React, { useContext } from 'react' @@ -20,6 +19,7 @@ import { PRODUCTION_MANUSCRIPT_UPDATE, SUBMIT_AUTHOR_PROOFING_FEEDBACK, UPDATE_TEMPLATE, + CURRENT_USER, } from '../../../../queries' const showAuthorProofingMode = ( @@ -49,7 +49,7 @@ const showAuthorProofingMode = ( ) } -const ProductionPage = ({ currentUser }) => { +const ProductionPage = () => { const params = useParams() const { groupId, controlPanel, submission } = useContext(ConfigContext) const client = useApolloClient() @@ -118,6 +118,9 @@ const ProductionPage = ({ currentUser }) => { // }, }) + const { data: currentUserData } = useQuery(CURRENT_USER) + const currentUser = currentUserData.currentUser + const [update] = useMutation(PRODUCTION_MANUSCRIPT_UPDATE) const [submitAuthorProofingFeedback] = useMutation( diff --git a/packages/client/app/components/component-profile/src/ProfilePage.jsx b/packages/client/app/components/component-profile/src/ProfilePage.jsx index 6064c0854..9de547ef2 100644 --- a/packages/client/app/components/component-profile/src/ProfilePage.jsx +++ b/packages/client/app/components/component-profile/src/ProfilePage.jsx @@ -1,4 +1,3 @@ -/* eslint-disable react/prop-types */ /* eslint-disable promise/catch-or-return */ /* eslint-disable promise/always-return */ @@ -21,16 +20,22 @@ import { UPDATE_LANGUAGE, GET_GLOBAL_CHAT_NOTIFICATION_OPTION, UPDATE_GLOBAL_CHAT_NOTIFICATION_OPTION, + CURRENT_USER, } from '../../../queries' const { version: kotahiVersion } = packageJson -const ProfilePage = ({ currentUser }) => { +const ProfilePage = () => { const { id } = useParams() const { urlFrag } = useContext(ConfigContext) const [didLogout, setDidLogout] = useState(false) + const { data: currentUserData, loading: currentUserLoading } = + useQuery(CURRENT_USER) + + const currentUser = currentUserData?.currentUser + const { loading, error, @@ -70,7 +75,7 @@ const ProfilePage = ({ currentUser }) => { }) } - if (loading) return + if (loading || currentUserLoading) return if (error) return if (didLogout) { diff --git a/packages/client/app/components/component-review/src/components/DecisionPage.jsx b/packages/client/app/components/component-review/src/components/DecisionPage.jsx index bbf11bf48..2fa15c1d2 100644 --- a/packages/client/app/components/component-review/src/components/DecisionPage.jsx +++ b/packages/client/app/components/component-review/src/components/DecisionPage.jsx @@ -1,5 +1,5 @@ /* eslint-disable react-hooks/immutability */ -/* eslint-disable react/prop-types */ + /* eslint-disable promise/catch-or-return, promise/always-return */ import { useEffect, useState, useContext } from 'react' @@ -58,6 +58,7 @@ import { NEW_REVIEW_FRAGMENT, NEW_TEAM_FRAGMENT, UPDATE_ADA, + CURRENT_USER, } from '../../../../queries' import { validateDoi, validateSuffix } from '../../../../shared/commsUtils' @@ -69,7 +70,7 @@ import { getRoles } from '../../../../shared/manuscriptUtils' let debouncers = {} -const DecisionPage = ({ currentUser }) => { +const DecisionPage = () => { const params = useParams() const manuscriptId = params.version @@ -84,6 +85,9 @@ const DecisionPage = ({ currentUser }) => { skip: true, }) + const { data: currentUserData } = useQuery(CURRENT_USER) + const currentUser = currentUserData.currentUser + useEffect(() => { return () => { Object.values(debouncers).forEach(d => d.flush()) diff --git a/packages/client/app/components/component-review/src/components/ReviewPage.jsx b/packages/client/app/components/component-review/src/components/ReviewPage.jsx index 9197ae8bc..44d0f9e46 100644 --- a/packages/client/app/components/component-review/src/components/ReviewPage.jsx +++ b/packages/client/app/components/component-review/src/components/ReviewPage.jsx @@ -19,17 +19,22 @@ import { MANUSCRIPT, EXPAND_CHAT, REVIEW_FORM_UPDATED, + CURRENT_USER, } from '../../../../queries' import useChat from '../../../../hooks/useChat' import { getCurrentUserReview } from './review/util' -const ReviewPage = ({ currentUser }) => { +const ReviewPage = () => { const params = useParams() const { t } = useTranslation() const config = useContext(ConfigContext) const { urlFrag } = config + + const { data: currentUserData } = useQuery(CURRENT_USER) + const currentUser = currentUserData.currentUser + const [updateReviewMutation] = useMutation(UPDATE_REVIEW) const [updateReviewerStatus] = useMutation(UPDATE_REVIEWER_STATUS) const [createFile] = useMutation(CREATE_FILE) diff --git a/packages/client/app/components/component-review/src/components/ReviewPreviewPage.jsx b/packages/client/app/components/component-review/src/components/ReviewPreviewPage.jsx index c3177deea..ad1cb08fc 100644 --- a/packages/client/app/components/component-review/src/components/ReviewPreviewPage.jsx +++ b/packages/client/app/components/component-review/src/components/ReviewPreviewPage.jsx @@ -1,18 +1,19 @@ -/* eslint-disable react/prop-types */ - import { useContext } from 'react' import { useQuery } from '@apollo/client/react' +import { useParams } from 'react-router-dom' + import ReviewPreview from './reviewPreview/ReviewPreview' import { Heading, Page, Spinner } from '../../../shared' import { ConfigContext } from '../../../config/src' import { REVIEW_PREVIEW_MANUSCRIPT } from '../../../../queries' -const ReviewPreviewPage = ({ match }) => { +const ReviewPreviewPage = () => { const config = useContext(ConfigContext) + const { version } = useParams() const { loading, error, data } = useQuery(REVIEW_PREVIEW_MANUSCRIPT, { variables: { - id: match.params.version, + id: version, groupId: config.groupId, }, partialRefetch: true, diff --git a/packages/client/app/components/component-submit/src/components/NewSubmissionPage.jsx b/packages/client/app/components/component-submit/src/components/NewSubmissionPage.jsx index 4e6dfe232..f54a7eeac 100644 --- a/packages/client/app/components/component-submit/src/components/NewSubmissionPage.jsx +++ b/packages/client/app/components/component-submit/src/components/NewSubmissionPage.jsx @@ -1,10 +1,11 @@ import { useContext } from 'react' import PropTypes from 'prop-types' -import { useApolloClient } from '@apollo/client/react' +import { useApolloClient, useQuery } from '@apollo/client/react' import { useTranslation } from 'react-i18next' import { Container, Content, UploadContainer, Heading } from '../style' import UploadManuscript from './UploadManuscript' import { ConfigContext } from '../../../config/src' +import { CURRENT_USER } from '../../../../queries' const acceptUploadFiles = [ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', @@ -25,10 +26,15 @@ const acceptFiles = ? acceptUploadFiles.join() : 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' -const Dashboard = ({ currentUser }) => { +const Dashboard = () => { const client = useApolloClient() const { t } = useTranslation() + const { data: currentUserData } = useQuery(CURRENT_USER) + + // @ts-ignore + const currentUser = currentUserData.currentUser + const { submission: { submissionPage }, } = useContext(ConfigContext) diff --git a/packages/client/app/components/component-submit/src/components/SubmitPage.jsx b/packages/client/app/components/component-submit/src/components/SubmitPage.jsx index 5d232beae..1fc05f54a 100644 --- a/packages/client/app/components/component-submit/src/components/SubmitPage.jsx +++ b/packages/client/app/components/component-submit/src/components/SubmitPage.jsx @@ -1,5 +1,3 @@ -/* eslint-disable react/prop-types */ - import { useState, useEffect, useContext } from 'react' import { useNavigate, useParams, useLocation } from 'react-router-dom' import { debounce, set } from 'lodash' @@ -28,6 +26,7 @@ import { CREATE_NEW_MANUSCRIPT_VERSION, CREATE_FILE, DELETE_FILE, + CURRENT_USER, } from '../../../../queries' let debouncers = {} @@ -48,7 +47,7 @@ const useValidateORCID = () => { return { validationOrcid } } -const SubmitPage = ({ currentUser }) => { +const SubmitPage = () => { const navigate = useNavigate() const params = useParams() const location = useLocation() @@ -70,6 +69,9 @@ const SubmitPage = ({ currentUser }) => { const decisionPurpose = 'decision' const reviewPurpose = 'review' + const { data: currentUserData } = useQuery(CURRENT_USER) + const currentUser = currentUserData.currentUser + const { data, loading, error } = useQuery( USER_MANUSCRIPT, { diff --git a/packages/client/app/components/component-submit/src/components/SubmitRedirect.tsx b/packages/client/app/components/component-submit/src/components/SubmitRedirect.tsx new file mode 100644 index 000000000..9a500af43 --- /dev/null +++ b/packages/client/app/components/component-submit/src/components/SubmitRedirect.tsx @@ -0,0 +1,28 @@ +import { type ReactNode, useContext } from 'react' +import { Navigate, useLocation, useParams } from 'react-router-dom' + +import { ConfigContext } from '../../../config/src' +import SubmitPage from './SubmitPage' + +const SubmitRedirect = (): ReactNode => { + const location = useLocation() + const { groupName, version } = useParams() + const config = useContext(ConfigContext) + + const isPreprint = ['preprint1', 'preprint2'].includes(config.instanceName) + const onEvaluation = location.pathname.endsWith('/evaluation') + + if (isPreprint && !onEvaluation) { + return ( + + ) + } + + if (!isPreprint && onEvaluation) { + return + } + + return +} + +export default SubmitRedirect diff --git a/packages/client/app/components/component-users-manager/src/UsersPage.jsx b/packages/client/app/components/component-users-manager/src/UsersPage.jsx index f529613ee..6a0f24de9 100644 --- a/packages/client/app/components/component-users-manager/src/UsersPage.jsx +++ b/packages/client/app/components/component-users-manager/src/UsersPage.jsx @@ -1,5 +1,3 @@ -/* eslint-disable react/prop-types */ - import { useLocation } from 'react-router-dom' import { useQuery, useMutation } from '@apollo/client/react' import { CommsErrorBanner, Spinner } from '../../shared' @@ -16,6 +14,7 @@ import { DELETE_USER, SET_GROUP_ROLE, SET_GLOBAL_ROLE, + CURRENT_USER, } from '../../../queries' const defaultSortDirections = { @@ -25,10 +24,13 @@ const defaultSortDirections = { groupManager: 'ASC', } -const UsersPage = ({ currentUser }) => { +const UsersPage = () => { const location = useLocation() const applyQueryParams = useQueryParams() + const { data: currentUserData } = useQuery(CURRENT_USER) + const currentUser = currentUserData.currentUser + const params = new URLSearchParams(location.search) const page = params.get(URI_PAGENUM_PARAM) || 1 const sortName = extractSortData(params).name || 'created' From 9979b9bfcefc2c7e6b7de54e69718219a98d6204 Mon Sep 17 00:00:00 2001 From: yannis Date: Mon, 15 Jun 2026 16:12:02 +0300 Subject: [PATCH 05/16] refactor(client): organize root queries --- packages/client/app/Pages.jsx | 110 +---------------- packages/client/app/Router.tsx | 90 ++++++-------- packages/client/app/components/AdminPage.jsx | 56 --------- .../src/{GroupPage.jsx => GroupsPage.jsx} | 45 ++++--- .../components/component-login/src/Login.jsx | 2 +- .../client/app/components/pubsweet/Button.jsx | 52 ++------ .../client/app/components/theme/src/index.jsx | 20 ---- .../client/app/pages/Authenticated.page.tsx | 68 +++++++++++ packages/client/app/pages/Group.page.tsx | 113 ++++++++++++++++++ .../client/app/pages/GroupWrapper.page.tsx | 38 ------ packages/client/app/pages/Menu.page.tsx | 5 +- packages/client/app/pages/index.ts | 3 +- packages/client/app/theme/color.js | 10 ++ packages/client/app/theme/index.jsx | 8 +- .../client/app/ui/base/ErrorPageFallback.tsx | 52 ++++++++ 15 files changed, 328 insertions(+), 344 deletions(-) delete mode 100644 packages/client/app/components/AdminPage.jsx rename packages/client/app/components/component-frontpage/src/{GroupPage.jsx => GroupsPage.jsx} (71%) delete mode 100644 packages/client/app/components/theme/src/index.jsx create mode 100644 packages/client/app/pages/Authenticated.page.tsx create mode 100644 packages/client/app/pages/Group.page.tsx delete mode 100644 packages/client/app/pages/GroupWrapper.page.tsx create mode 100644 packages/client/app/ui/base/ErrorPageFallback.tsx diff --git a/packages/client/app/Pages.jsx b/packages/client/app/Pages.jsx index 5cc3e7786..aca91483a 100644 --- a/packages/client/app/Pages.jsx +++ b/packages/client/app/Pages.jsx @@ -1,132 +1,32 @@ -/* eslint-disable react-hooks/exhaustive-deps */ - -import { useEffect } from 'react' -import { useLocation } from 'react-router-dom' -import styled from 'styled-components' -import { useQuery } from '@apollo/client/react' import Modal from 'react-modal' +import { ThemeProvider } from 'styled-components' -import { grid } from '@coko/client' - -import { ConfigProvider } from './components/config/src' -import { DynamicThemeProvider } from './components/theme/src' -import { YjsProvider } from './components/provider-yjs/YjsProvider' -import theme, { setBrandColors } from './theme' +import theme from './theme' import GlobalStyle from './theme/elements/GlobalStyle' -import { Spinner, CommsErrorBanner } from './components/shared' -import DynamicFavicon from './dynamicFavicon' - -import { GET_GROUPS } from './queries' import AssetManager from './components/asset-manager/src/AssetManagerPage' import { JournalProvider } from './components/xpub-journal' import journal from '../config/journal' import ModalProvider from './components/asset-manager/src/ui/Modal/ModalProvider' import { XpubProvider } from './components/xpub-with-context/src/index' -import { reloadTranslationsForGroup } from './i18n' import Router from './Router' -const Container = styled.div` - display: grid; - height: 10vh; - place-items: center; -` - -const Content = styled.div` - margin-bottom: 1rem; - max-width: 40em; - padding: ${grid(4)}; - text-align: center; - - h1 { - margin-bottom: ${grid(2)}; - } -` - -const Centered = styled.div` - text-align: center; -` - const modals = { assetManagerEditor: AssetManager, } const Pages = () => { Modal.setAppElement('#root') - const location = useLocation() - - const { loading, error, data } = useQuery(GET_GROUPS) - - const groups = data?.groups ? data.groups : [] - - let currentGroup = null - - const name = location.pathname.split('/')[1] - - if (name) { - currentGroup = groups.find(group => group.name === name) - } - - const activeConfig = currentGroup?.configs?.find(config => config?.active) - - useEffect(() => { - reloadTranslationsForGroup( - currentGroup?.name, - JSON.parse(activeConfig?.translationOverrides || '{}'), - ) - }, [currentGroup?.id, activeConfig?.id]) - - if (loading && !data) return - - if (error) - return ( - - - - - - - - ) - - window.localStorage.setItem('groupId', currentGroup?.id) - - // TODO: Remove old config once refactor of config is completed - const oldConfig = JSON.parse(currentGroup?.oldConfig || '{}') - - const config = { - id: activeConfig?.id, - groupId: currentGroup?.id, - groupName: currentGroup?.name, - formData: activeConfig?.formData, - urlFrag: `/${currentGroup?.name}`, - logo: activeConfig?.logo, - icon: activeConfig?.icon, - flaxSiteUrl: activeConfig?.flaxSiteUrl, - ...oldConfig, - ...JSON.parse(activeConfig?.formData || '{}'), - } - - // Overwrites config theme colors - setBrandColors( - config?.groupIdentity?.primaryColor, - config?.groupIdentity?.secondaryColor, - ) return ( - - + - - - - - - + + diff --git a/packages/client/app/Router.tsx b/packages/client/app/Router.tsx index 5d9f4d66f..fb7f8ca84 100644 --- a/packages/client/app/Router.tsx +++ b/packages/client/app/Router.tsx @@ -1,5 +1,5 @@ import { type ReactNode, useContext } from 'react' -import { Route, Routes, Navigate, Outlet, useParams } from 'react-router-dom' +import { Route, Routes, Navigate, Outlet } from 'react-router-dom' import { useQuery } from '@apollo/client/react' import AcceptArticleOwnershipPage from './components/component-dashboard/src/components/AcceptArticleOwnershipPage' @@ -19,7 +19,7 @@ import DashboardSubmissionsPage from './components/component-dashboard/src/compo import DecisionPage from './components/component-review/src/components/DecisionPage' import DeclineArticleOwnershipPage from './components/component-dashboard/src/components/DeclineArticleOwnershipPage' import FormBuilderPage from './components/component-formbuilder/src/components/FormBuilderPage' -import GroupPage from './components/component-frontpage/src/GroupPage' +import GroupsPage from './components/component-frontpage/src/GroupsPage' import InvitationAcceptedPage from './components/component-dashboard/src/components/InvitationAcceptedPage' import Login from './components/component-login/src' import ManuscriptPage from './components/component-manuscript/src/components/ManuscriptPage' @@ -38,32 +38,13 @@ import UsersPage from './components/component-users-manager/src/UsersPage' import { ConfigContext } from './components/config/src' import { XpubContext } from './components/xpub-with-context/src' -import { GroupWrapperPage, MenuPage } from './pages' +import { AuthenticatedPage, GroupPage, MenuPage } from './pages' import { CURRENT_USER } from './queries' import Layout from './ui/base/Layout' // #region helpers -const Authenticated = (): ReactNode => { - const { groupName } = useParams() - - // if ( - // ['journal', 'prc'].includes(instanceName) && - // currentUser && - // !currentUser.email && - // path !== `${urlFrag}/profile` // TODO configure this url via config manager - // ) { - // return - // } - - if (!localStorage.getItem('token')) { - return - } - - return -} - enum Role { // global Admin = 'admin', @@ -113,16 +94,43 @@ const RoleGate = (props: RoleGateProps): ReactNode => { } // #endregion helpers +/** + * TO DO - dashboard tabs don't need to be separate urls + * (OR dashboard does not need tabs at all ???) + * + * kept separate here in order to call config context within config provider + * (config provider starts at /:groupName) + * + * Clean solution for the above is to not use config in the router and simply + * hide / show sections in the ui + */ +const DashboardRoutes = (): ReactNode => { + const config = useContext(ConfigContext) + return ( + + } path="" /> + {config?.dashboard?.showSections?.includes('submission') && ( + } path="submissions" /> + )} + {config?.dashboard?.showSections?.includes('review') && ( + } path="reviews" /> + )} + {config?.dashboard?.showSections?.includes('editor') && ( + } path="edits" /> + )} + + ) +} + const Router = (): ReactNode => { // TO DO - look into how to get rid of these two const [conversion] = useContext(XpubContext) - const config = useContext(ConfigContext) return ( - } path="/" /> + } path="/" /> - } path="/:groupName"> + } path="/:groupName"> } index /> } path="login" /> @@ -148,7 +156,7 @@ const Router = (): ReactNode => { path="versions/:version/artifacts/:artifactId" /> - }> + }> @@ -193,39 +201,15 @@ const Router = (): ReactNode => { - - } path="" /> - - {config?.dashboard?.showSections?.includes( - 'submission', - ) && ( - } - path="submissions" - /> - )} - - {config?.dashboard?.showSections?.includes('review') && ( - } - path="reviews" - /> - )} - - {config?.dashboard?.showSections?.includes('editor') && ( - } path="edits" /> - )} - + } path="dashboard/*" /> - + } > @@ -249,7 +233,7 @@ const Router = (): ReactNode => { } path="users" /> } path="tasks" /> - + } path="pages/:pageId?" /> } path="layout" /> } path="article" /> diff --git a/packages/client/app/components/AdminPage.jsx b/packages/client/app/components/AdminPage.jsx deleted file mode 100644 index 2a6d40f58..000000000 --- a/packages/client/app/components/AdminPage.jsx +++ /dev/null @@ -1,56 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps, react-hooks/immutability, react-hooks/refs */ - -import { useMutation, useQuery } from '@apollo/client/react' - -import { useContext, useEffect, useRef } from 'react' -import i18next from 'i18next' -import { JournalContext } from './xpub-journal' - -import { getLanguages } from '../i18n' - -import { CURRENT_USER, UPDATE_LANGUAGE } from '../queries' - -import { Spinner } from './shared' - -const AdminPage = () => { - const journal = useContext(JournalContext) - - const { loading, data } = useQuery(CURRENT_USER, { - fetchPolicy: 'network-only', - pollInterval: 120000, - }) - - const previousDataRef = useRef(null) - - const [updateLanguage] = useMutation(UPDATE_LANGUAGE) - useEffect(() => { - if (!data?.currentUser) return - - if (!data.currentUser.preferredLanguage) { - updateLanguage({ - variables: { id: currentUser.id, preferredLanguage: i18next.language }, - }) - } else { - const languageValues = getLanguages().map(l => l.value) - i18next.changeLanguage( - languageValues.includes(currentUser.preferredLanguage) - ? currentUser.preferredLanguage - : 'en', - ) - } - }, [data?.currentUser]) - - // Do this to prevent polling-related flicker - if (loading && !previousDataRef.current) { - return - } - - const currentUser = data?.currentUser - journal.textStyles = data?.builtCss?.css - - previousDataRef.current = data - - return null -} - -export default AdminPage diff --git a/packages/client/app/components/component-frontpage/src/GroupPage.jsx b/packages/client/app/components/component-frontpage/src/GroupsPage.jsx similarity index 71% rename from packages/client/app/components/component-frontpage/src/GroupPage.jsx rename to packages/client/app/components/component-frontpage/src/GroupsPage.jsx index d39ba2351..4a833e273 100644 --- a/packages/client/app/components/component-frontpage/src/GroupPage.jsx +++ b/packages/client/app/components/component-frontpage/src/GroupsPage.jsx @@ -7,9 +7,7 @@ import { th, grid } from '@coko/client' import styled from 'styled-components' import { Spinner, CommsErrorBanner, Select } from '../../shared' import { GET_GROUPS } from '../../../queries' -import theme, { color } from '../../../theme' -import { DynamicThemeProvider } from '../../theme/src' -import GlobalStyle from '../../../theme/elements/GlobalStyle' +import { color } from '../../../theme' const Container = styled.div` background: ${color.gray97}; @@ -43,7 +41,7 @@ export const capitalizeFirstLetter = string => { return string.charAt(0).toUpperCase() + string.slice(1) } -const GroupPage = () => { +const GroupsPage = () => { const navigate = useNavigate() const [selectedOption, setSelectedOption] = useState('') const { loading, error, data } = useQuery(GET_GROUPS) @@ -81,27 +79,24 @@ const GroupPage = () => { }) return ( - - - - - Select group to login - { - redirectToLogin(selected.value) - }} - options={groups} - placeholder="Select group" - value={selectedOption} - width="100%" - /> - - - + + + Select group to login + { + redirectToLogin(selected.value) + }} + options={groups} + placeholder="Select group" + value={selectedOption} + width="100%" + /> + + ) } -export default GroupPage +export default GroupsPage diff --git a/packages/client/app/components/component-login/src/Login.jsx b/packages/client/app/components/component-login/src/Login.jsx index 5882199e7..72fe6ef64 100644 --- a/packages/client/app/components/component-login/src/Login.jsx +++ b/packages/client/app/components/component-login/src/Login.jsx @@ -65,7 +65,7 @@ const Container = styled.div.attrs({ const Content = styled.div` background: ${th('colorBackground')}; border-radius: ${th('borderRadius')}; - box-shadow: ${th('boxShadow')}; + box-shadow: ${th('boxShadow.shades.200')}; margin-bottom: 1rem; max-width: 40em; padding: ${grid(4)}; diff --git a/packages/client/app/components/pubsweet/Button.jsx b/packages/client/app/components/pubsweet/Button.jsx index 479ec073f..c29899506 100644 --- a/packages/client/app/components/pubsweet/Button.jsx +++ b/packages/client/app/components/pubsweet/Button.jsx @@ -1,5 +1,5 @@ import styled, { css } from 'styled-components' -import { darken, override, th } from '@coko/client' +import { darken, override, th, grid } from '@coko/client' const StyledButton = styled.button.attrs(props => ({ 'data-testid': props['data-testid'], @@ -8,16 +8,13 @@ const StyledButton = styled.button.attrs(props => ({ background: ${th('colorSecondary')}; border: ${th('borderWidth')} ${th('borderStyle')} ${th('colorBorder')}; border-radius: ${th('borderRadius')}; - color: ${props => (props.color ? props.color : props.theme.colorText)}; - cursor: ${p => (p.disabled ? 'not-allowed' : 'pointer')}; + color: ${th('colorText')}; + cursor: ${props => (props.disabled ? 'not-allowed' : 'pointer')}; font-family: ${th('fontInterface')}; - font-size: ${props => - props.size === 'small' - ? props.theme.fontSizeBaseSmall - : props.theme.fontSizeBase}; - line-height: calc(${th('gridUnit')} * 3); - min-width: calc(${th('gridUnit')} * 12); - padding: ${props => (props.size === 'small' ? '0' : props.theme.gridUnit)}; + font-size: ${th('fontSizeBase')}; + line-height: ${grid(3)}; + min-width: ${grid(12)}; + padding: ${grid(1)}; &:focus, &:hover { @@ -43,52 +40,27 @@ const StyledButton = styled.button.attrs(props => ({ ${props => props.$primary && css` - background: ${props.background - ? props.background - : props.theme.colorPrimary}; - - color: ${props.color ? props.color : props.theme.colorTextReverse}; + background: ${th('colorPrimary')}; + color: ${th('colorTextReverse')}; &:focus, &:hover { - background-color: ${props.background - ? darken(props.background, 0.3) - : darken(props.theme.colorPrimary, 0.3)}; + background-color: ${darken('colorPrimary', 0.3)}; } &:active { - background-color: ${props.background - ? darken(props.background, 0.5) - : darken(props.theme.colorPrimary, 0.5)}; + background-color: ${darken('colorPrimary', 0.5)}; } &[disabled] { &:focus, &:hover, &:active { - background: ${props.background - ? props.background - : props.theme.colorPrimary}; + background: ${th('colorPrimary')}; } } `}; - ${props => - props.outline && - css` - border: ${th('borderWidth')} ${th('borderStyle')} - ${props.color ? props.color : props.colorPrimary}; - padding: ${props.size === 'small' ? '0' : props.theme.gridUnit}; - text-decoration: none; - - &:hover, - &:focus, - &:active { - border: ${th('borderWidth')} ${th('borderStyle')} - ${props.color ? props.color : props.colorPrimary}; - } - `}; - ${override('ui.Button')}; ` diff --git a/packages/client/app/components/theme/src/index.jsx b/packages/client/app/components/theme/src/index.jsx deleted file mode 100644 index bbbf84fb9..000000000 --- a/packages/client/app/components/theme/src/index.jsx +++ /dev/null @@ -1,20 +0,0 @@ -/* eslint-disable react/prop-types */ - -import { createContext, useState } from 'react' -import { ThemeProvider } from 'styled-components' - -const ThemeUpdateContext = createContext() - -const DynamicThemeProvider = ({ theme, children }) => { - const [myTheme, setMyTheme] = useState(theme) - - return ( - - - {children} - - - ) -} - -export { ThemeUpdateContext, DynamicThemeProvider } diff --git a/packages/client/app/pages/Authenticated.page.tsx b/packages/client/app/pages/Authenticated.page.tsx new file mode 100644 index 000000000..a1f91dfc3 --- /dev/null +++ b/packages/client/app/pages/Authenticated.page.tsx @@ -0,0 +1,68 @@ +/* eslint-disable react-hooks/immutability */ + +import { type ReactNode, useContext, useEffect } from 'react' +import { Outlet, Navigate, useParams } from 'react-router-dom' +import { useMutation, useQuery } from '@apollo/client/react' +import i18next from 'i18next' + +import { CURRENT_USER, UPDATE_LANGUAGE } from '../queries' +import { Spinner } from '../components/shared' +import { JournalContext } from '../components/xpub-journal' +import { getLanguages } from '../i18n' + +const AuthenticatedPage = (): ReactNode => { + const { groupName } = useParams() + const journal = useContext(JournalContext) + + const { loading, data, previousData } = useQuery(CURRENT_USER, { + fetchPolicy: 'network-only', + pollInterval: 120000, + skip: !localStorage.getItem('token'), + }) + + // @ts-ignore + const currentUser = data?.currentUser + + const [updateLanguage] = useMutation(UPDATE_LANGUAGE) + + // TO DO - this likely needs to be checked + useEffect(() => { + if (currentUser) { + if (!currentUser.preferredLanguage) { + updateLanguage({ + variables: { + id: currentUser.id, + preferredLanguage: i18next.language, + }, + }) + } else { + const languageValues = getLanguages().map(l => l.value) + i18next.changeLanguage( + languageValues.includes(currentUser.preferredLanguage) + ? currentUser.preferredLanguage + : 'en', + ) + } + } + }, [currentUser, updateLanguage]) + + // Do this to prevent polling-related flicker + if (loading && !previousData) { + return + } + + if (!currentUser) { + // TO DO - reuse a logout function here that clearn cache etc. + localStorage.removeItem('token') + return + } + + // TO DO - we do not need to keep this info in the context. we just need to + // read the query data. + // @ts-ignore + journal.textStyles = data?.builtCss?.css + + return +} + +export default AuthenticatedPage diff --git a/packages/client/app/pages/Group.page.tsx b/packages/client/app/pages/Group.page.tsx new file mode 100644 index 000000000..c7d8f984e --- /dev/null +++ b/packages/client/app/pages/Group.page.tsx @@ -0,0 +1,113 @@ +import { type ReactNode, useEffect } from 'react' +import { useParams, Outlet } from 'react-router-dom' +import { useQuery } from '@apollo/client/react' +import { ThemeProvider } from 'styled-components' + +import { GET_GROUPS } from '../queries' +import { reloadTranslationsForGroup } from '../i18n' +import { + setBrandColors, + colorPrimaryDefault, + colorSecondaryDefault, +} from '../theme' +import { Spinner, PageError } from '../components/shared' +import ErrorPageFallback from '../ui/base/ErrorPageFallback' +import { ConfigProvider } from '../components/config/src' +import { YjsProvider } from '../components/provider-yjs/YjsProvider' +import DynamicFavicon from '../dynamicFavicon' +import { validateColor } from '../theme/color' + +type ThemeOverrides = { + colorPrimary?: string + colorSecondary?: string +} + +const GroupPage = (): ReactNode => { + const { groupName } = useParams() + + /** + * TO DO + * The get group query fetches a lot of data for all groups in the cache. + * Fetch something more minimal to grab the names(same goes for the login + * dropdown) and get the full single group afterwards. + */ + + const { loading, error, data } = useQuery(GET_GROUPS) + + // @ts-ignore + const currentGroup = data?.groups.find(group => group.name === groupName) + // @ts-ignore + const activeConfig = currentGroup?.configs?.find(config => config?.active) + + useEffect(() => { + reloadTranslationsForGroup( + currentGroup?.name, + JSON.parse(activeConfig?.translationOverrides || '{}'), + ) + }, [ + currentGroup?.id, + currentGroup?.name, + activeConfig?.id, + activeConfig?.translationOverrides, + ]) + + if (loading) return + + if (error) { + return + } + + if (!currentGroup) { + return + } + + window.localStorage.setItem('groupId', currentGroup.id) + + // TODO: Remove old config once refactor of config is completed + const oldConfig = JSON.parse(currentGroup?.oldConfig || '{}') + + const config = { + id: activeConfig?.id, + groupId: currentGroup?.id, + groupName: currentGroup?.name, + formData: activeConfig?.formData, + urlFrag: `/${currentGroup?.name}`, + logo: activeConfig?.logo, + icon: activeConfig?.icon, + flaxSiteUrl: activeConfig?.flaxSiteUrl, + ...oldConfig, + ...JSON.parse(activeConfig?.formData || '{}'), + } + + // TO DO - refactor colors so that the theme is not bypassed + setBrandColors( + config?.groupIdentity?.primaryColor, + config?.groupIdentity?.secondaryColor, + ) + + const groupThemeOverrides: ThemeOverrides = {} + + if (validateColor(config?.groupIdentity?.primaryColor)) { + groupThemeOverrides.colorPrimary = + config?.groupIdentity?.primaryColor || colorPrimaryDefault + } + + if (validateColor(config?.groupIdentity?.secondaryColor)) { + groupThemeOverrides.colorSecondary = + config?.groupIdentity?.secondaryColor || colorSecondaryDefault + } + + // TO DO - should yjs provider wrap the whole group? + return ( + + + + + + + + + ) +} + +export default GroupPage diff --git a/packages/client/app/pages/GroupWrapper.page.tsx b/packages/client/app/pages/GroupWrapper.page.tsx deleted file mode 100644 index ca76abe23..000000000 --- a/packages/client/app/pages/GroupWrapper.page.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { type ReactNode } from 'react' -import { useParams, Outlet } from 'react-router-dom' -import { useQuery } from '@apollo/client/react' - -import { GET_GROUPS } from '../queries' - -const GroupWrapper = (): ReactNode => { - const { groupName } = useParams() - - /** - * TO DO - * The get group query fetches a lot of data for all groups in the cache. - * Fetch something more minimal to grab the names(same goes for the login - * dropdown) and get the full single group afterwards. - */ - - const { loading, error, data } = useQuery(GET_GROUPS) - - // TO DO - show spinner - if (loading) return null - - if (error) { - // TO DO - show nicer message - return `Something went wrong` - } - - // @ts-ignore - const currentGroup = data.groups.find(group => group.name === groupName) - - if (!currentGroup) { - // TO DO - show nicer message - return `No group named ${groupName}` - } - - return -} - -export default GroupWrapper diff --git a/packages/client/app/pages/Menu.page.tsx b/packages/client/app/pages/Menu.page.tsx index aa8768558..ed1b16941 100644 --- a/packages/client/app/pages/Menu.page.tsx +++ b/packages/client/app/pages/Menu.page.tsx @@ -29,10 +29,7 @@ const MenuPage = (): ReactNode => { const { urlFrag, instanceName } = config // TO DO - this should be in a more generic place than the menu - const { loading, error, data } = useQuery(CURRENT_USER, { - fetchPolicy: 'network-only', - pollInterval: 120000, - }) + const { loading, error, data } = useQuery(CURRENT_USER) if (loading) return null diff --git a/packages/client/app/pages/index.ts b/packages/client/app/pages/index.ts index 1df1e9e2f..c3a9752d7 100644 --- a/packages/client/app/pages/index.ts +++ b/packages/client/app/pages/index.ts @@ -1,2 +1,3 @@ -export { default as GroupWrapperPage } from './GroupWrapper.page' +export { default as AuthenticatedPage } from './Authenticated.page' +export { default as GroupPage } from './Group.page' export { default as MenuPage } from './Menu.page' diff --git a/packages/client/app/theme/color.js b/packages/client/app/theme/color.js index 006c11ce6..b3770ff57 100644 --- a/packages/client/app/theme/color.js +++ b/packages/client/app/theme/color.js @@ -6,6 +6,16 @@ import lightenBy from '../shared/lightenBy' const defaultBrandColor1 = '#2fac66' const defaultBrandColor2 = '#704f79' +export const validateColor = colorCode => { + try { + Color(colorCode) + return colorCode + } catch { + console.error(`${colorCode} is not a valid color code`) + return null + } +} + const validateInstanceConfigColors = (colorCode, fallbackColor) => { try { Color(colorCode) diff --git a/packages/client/app/theme/index.jsx b/packages/client/app/theme/index.jsx index b51268221..4b4fe46ad 100644 --- a/packages/client/app/theme/index.jsx +++ b/packages/client/app/theme/index.jsx @@ -199,7 +199,13 @@ const cokoTheme = { }, } -export const setBrandColors = (color1 = '#3AAE2A', color2 = '#9e9e9e') => { +export const colorPrimaryDefault = '#3aae2a' +export const colorSecondaryDefault = '#9e9e9e' + +export const setBrandColors = ( + color1 = colorPrimaryDefault, + color2 = colorSecondaryDefault, +) => { cokoTheme.colorPrimary = color1 cokoTheme.colorSecondary = color2 internalSetBrandColors(color1, color2) diff --git a/packages/client/app/ui/base/ErrorPageFallback.tsx b/packages/client/app/ui/base/ErrorPageFallback.tsx new file mode 100644 index 000000000..80c84780f --- /dev/null +++ b/packages/client/app/ui/base/ErrorPageFallback.tsx @@ -0,0 +1,52 @@ +import { type ReactNode } from 'react' +import styled from 'styled-components' + +import { grid } from '@coko/client' + +import { CommsErrorBanner } from '../../components/shared' + +const Wrapper = styled.div`` + +const Container = styled.div` + display: grid; + height: 10vh; + place-items: center; +` + +const Content = styled.div` + margin-bottom: 1rem; + max-width: 40em; + padding: ${grid(4)}; + text-align: center; + + h1 { + margin-bottom: ${grid(2)}; + } +` + +const Centered = styled.div` + text-align: center; +` + +type ErrorPageFallbackProps = { + className?: string + error?: any +} + +const ErrorPageFallback = (props: ErrorPageFallbackProps): ReactNode => { + const { className, error } = props + + return ( + + + + + + + + + + ) +} + +export default ErrorPageFallback From fde4c250ceeb29144def40ba5d92130ea4334700 Mon Sep 17 00:00:00 2001 From: yannis Date: Tue, 16 Jun 2026 10:10:52 +0300 Subject: [PATCH 06/16] fix(client): make sure to redirect to profile is user has no email --- packages/client/app/pages/Authenticated.page.tsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/client/app/pages/Authenticated.page.tsx b/packages/client/app/pages/Authenticated.page.tsx index a1f91dfc3..ce199be9a 100644 --- a/packages/client/app/pages/Authenticated.page.tsx +++ b/packages/client/app/pages/Authenticated.page.tsx @@ -1,17 +1,20 @@ /* eslint-disable react-hooks/immutability */ import { type ReactNode, useContext, useEffect } from 'react' -import { Outlet, Navigate, useParams } from 'react-router-dom' +import { Outlet, Navigate, useParams, useLocation } from 'react-router-dom' import { useMutation, useQuery } from '@apollo/client/react' import i18next from 'i18next' import { CURRENT_USER, UPDATE_LANGUAGE } from '../queries' import { Spinner } from '../components/shared' import { JournalContext } from '../components/xpub-journal' +import { ConfigContext } from '../components/config/src' import { getLanguages } from '../i18n' const AuthenticatedPage = (): ReactNode => { + const { pathname } = useLocation() const { groupName } = useParams() + const config = useContext(ConfigContext) const journal = useContext(JournalContext) const { loading, data, previousData } = useQuery(CURRENT_USER, { @@ -62,6 +65,15 @@ const AuthenticatedPage = (): ReactNode => { // @ts-ignore journal.textStyles = data?.builtCss?.css + if ( + ['journal', 'prc'].includes(config.instanceName) && + currentUser && + !currentUser.email && + pathname !== `/${groupName}/profile` // TODO configure this url via config manager + ) { + return + } + return } From fca392f2336fe4e38f6f95867bf11f980688fa64 Mon Sep 17 00:00:00 2001 From: yannis Date: Tue, 16 Jun 2026 10:34:14 +0300 Subject: [PATCH 07/16] fix(client): add useMemo for config in group page --- packages/client/app/pages/Group.page.tsx | 70 ++++++++++++++---------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/packages/client/app/pages/Group.page.tsx b/packages/client/app/pages/Group.page.tsx index c7d8f984e..b7013f5b3 100644 --- a/packages/client/app/pages/Group.page.tsx +++ b/packages/client/app/pages/Group.page.tsx @@ -1,4 +1,4 @@ -import { type ReactNode, useEffect } from 'react' +import { type ReactNode, useEffect, useMemo } from 'react' import { useParams, Outlet } from 'react-router-dom' import { useQuery } from '@apollo/client/react' import { ThemeProvider } from 'styled-components' @@ -51,6 +51,46 @@ const GroupPage = (): ReactNode => { activeConfig?.translationOverrides, ]) + const config = useMemo(() => { + // TODO: Remove old config once refactor of config is completed + const oldConfig = JSON.parse(currentGroup?.oldConfig || '{}') + + return { + id: activeConfig?.id, + groupId: currentGroup?.id, + groupName: currentGroup?.name, + formData: activeConfig?.formData, + urlFrag: `/${currentGroup?.name}`, + logo: activeConfig?.logo, + icon: activeConfig?.icon, + flaxSiteUrl: activeConfig?.flaxSiteUrl, + ...oldConfig, + ...JSON.parse(activeConfig?.formData || '{}'), + } + }, [ + currentGroup?.id, + currentGroup?.name, + currentGroup?.oldConfig, + activeConfig?.id, + activeConfig?.formData, + activeConfig?.logo, + activeConfig?.icon, + activeConfig?.flaxSiteUrl, + ]) + + const groupThemeOverrides: ThemeOverrides = useMemo(() => { + if (!config?.groupIdentity) return {} + + const { primaryColor, secondaryColor } = config.groupIdentity + const isPrimaryValid = validateColor(primaryColor) + const isSecondaryValid = validateColor(secondaryColor) + + return { + colorPrimary: isPrimaryValid ? primaryColor : colorPrimaryDefault, + colorSecondary: isSecondaryValid ? secondaryColor : colorSecondaryDefault, + } + }, [config]) + if (loading) return if (error) { @@ -63,40 +103,12 @@ const GroupPage = (): ReactNode => { window.localStorage.setItem('groupId', currentGroup.id) - // TODO: Remove old config once refactor of config is completed - const oldConfig = JSON.parse(currentGroup?.oldConfig || '{}') - - const config = { - id: activeConfig?.id, - groupId: currentGroup?.id, - groupName: currentGroup?.name, - formData: activeConfig?.formData, - urlFrag: `/${currentGroup?.name}`, - logo: activeConfig?.logo, - icon: activeConfig?.icon, - flaxSiteUrl: activeConfig?.flaxSiteUrl, - ...oldConfig, - ...JSON.parse(activeConfig?.formData || '{}'), - } - // TO DO - refactor colors so that the theme is not bypassed setBrandColors( config?.groupIdentity?.primaryColor, config?.groupIdentity?.secondaryColor, ) - const groupThemeOverrides: ThemeOverrides = {} - - if (validateColor(config?.groupIdentity?.primaryColor)) { - groupThemeOverrides.colorPrimary = - config?.groupIdentity?.primaryColor || colorPrimaryDefault - } - - if (validateColor(config?.groupIdentity?.secondaryColor)) { - groupThemeOverrides.colorSecondary = - config?.groupIdentity?.secondaryColor || colorSecondaryDefault - } - // TO DO - should yjs provider wrap the whole group? return ( From 4b86426da0da051ea01ed228b1a4dbfc31bd6b2a Mon Sep 17 00:00:00 2001 From: yannis Date: Tue, 16 Jun 2026 11:29:01 +0300 Subject: [PATCH 08/16] fix(client): fix polling flickering --- packages/client/app/pages/Authenticated.page.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/client/app/pages/Authenticated.page.tsx b/packages/client/app/pages/Authenticated.page.tsx index ce199be9a..926a1085e 100644 --- a/packages/client/app/pages/Authenticated.page.tsx +++ b/packages/client/app/pages/Authenticated.page.tsx @@ -17,9 +17,10 @@ const AuthenticatedPage = (): ReactNode => { const config = useContext(ConfigContext) const journal = useContext(JournalContext) - const { loading, data, previousData } = useQuery(CURRENT_USER, { + const { loading, data } = useQuery(CURRENT_USER, { fetchPolicy: 'network-only', - pollInterval: 120000, + pollInterval: 60000, + notifyOnNetworkStatusChange: false, // stops screen flickering skip: !localStorage.getItem('token'), }) @@ -49,8 +50,7 @@ const AuthenticatedPage = (): ReactNode => { } }, [currentUser, updateLanguage]) - // Do this to prevent polling-related flicker - if (loading && !previousData) { + if (loading) { return } From ad500db0002deafa2ed7c19bdb28640445ad0b96 Mon Sep 17 00:00:00 2001 From: yannis Date: Tue, 16 Jun 2026 14:43:45 +0300 Subject: [PATCH 09/16] chore(client): add comment on route --- packages/client/app/Router.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/app/Router.tsx b/packages/client/app/Router.tsx index fb7f8ca84..c91149357 100644 --- a/packages/client/app/Router.tsx +++ b/packages/client/app/Router.tsx @@ -150,7 +150,7 @@ const Router = (): ReactNode => { path="invitation/accepted" /> - {/* TO DO - should this be public? */} + {/* TO DO - still necessary? used by docmaps server-side */} } path="versions/:version/artifacts/:artifactId" From 3bdde0ee1957b771bb4f6dad703117849bbebed6 Mon Sep 17 00:00:00 2001 From: Yannis Barlas Date: Fri, 19 Jun 2026 13:01:46 +0300 Subject: [PATCH 10/16] chore(*): update changes.md --- CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 966fd3fa9..085e28e7f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,8 @@ #### Bug fixes +* We fixed a bug where a user could see another user's profile without the necessary permissions. Only admins can do that now. + #### Deployment changes ##### Job queue database connection From 66778fefa62a12a7ff91dde324ed29320833b81a Mon Sep 17 00:00:00 2001 From: yannis Date: Mon, 22 Jun 2026 15:24:49 +0300 Subject: [PATCH 11/16] test(*): fix e2e tests --- .../a-journal/004-assigning_editor_spec.cy.js | 1 + cypress/e2e/a-journal/005-decision_spec.cy.js | 2 +- .../b-colab-prc/101-profile_page_spec.cy.js | 17 +++------ .../b-colab-prc/104-control_page_spec.cy.js | 1 + .../107-new_manuscript_version_spec.cy.js | 5 +-- cypress/e2e/ncrc/300-login_page_spec.cy.js | 2 +- cypress/page-object/control-page.js | 7 ++-- cypress/support/routes1.js | 1 - .../src/components/DashboardEditsPage.jsx | 6 +-- .../src/components/DashboardRedirect.tsx | 8 +--- .../src/components/DashboardReviewsPage.jsx | 6 +-- .../components/DashboardSubmissionsPage.jsx | 6 +-- .../src/components/ManuscriptPage.jsx | 12 +++--- .../src/ManuscriptsPage.jsx | 8 ++-- .../src/components/ProductionPage.jsx | 6 +-- .../component-profile/src/ProfilePage.jsx | 11 ++---- .../src/components/DecisionPage.jsx | 38 +++++++++++++------ .../src/components/DecisionVersion.jsx | 3 +- .../src/components/ReviewPage.jsx | 8 ++-- .../src/components/NewSubmissionPage.jsx | 10 ++--- .../src/components/SubmitPage.jsx | 7 +--- .../component-users-manager/src/UsersPage.jsx | 6 +-- .../client/app/pages/Authenticated.page.tsx | 7 +++- .../client/app/pages/hooks/useCurrentUser.tsx | 15 ++++++++ packages/client/app/queries/team.queries.ts | 30 +++++++++++++++ 25 files changed, 128 insertions(+), 95 deletions(-) create mode 100644 packages/client/app/pages/hooks/useCurrentUser.tsx diff --git a/cypress/e2e/a-journal/004-assigning_editor_spec.cy.js b/cypress/e2e/a-journal/004-assigning_editor_spec.cy.js index 81baa8c9c..631c4cdf8 100644 --- a/cypress/e2e/a-journal/004-assigning_editor_spec.cy.js +++ b/cypress/e2e/a-journal/004-assigning_editor_spec.cy.js @@ -23,6 +23,7 @@ describe('Assigning editors and decision reject', () => { ManuscriptsPage.selectOptionWithText('Control') + cy.wait(1000) ControlPage.clickAssignSeniorEditorDropdown() ControlPage.selectDropdownOptionByName(name.role.seniorEditor) diff --git a/cypress/e2e/a-journal/005-decision_spec.cy.js b/cypress/e2e/a-journal/005-decision_spec.cy.js index 91244011d..3d805befb 100644 --- a/cypress/e2e/a-journal/005-decision_spec.cy.js +++ b/cypress/e2e/a-journal/005-decision_spec.cy.js @@ -23,7 +23,7 @@ describe('Completing a decision', () => { /* Group Manager assigns Editor to manuscript */ cy.login(name.role.admin, dashboard) - cy.wait(1000) + cy.wait(2000) DashboardPage.clickManuscriptNavButton() ManuscriptsPage.selectOptionWithText('Control') ControlPage.getAssignSeniorEditorDropdown().click({ force: true }) diff --git a/cypress/e2e/b-colab-prc/101-profile_page_spec.cy.js b/cypress/e2e/b-colab-prc/101-profile_page_spec.cy.js index 615d8338b..b9bab9868 100644 --- a/cypress/e2e/b-colab-prc/101-profile_page_spec.cy.js +++ b/cypress/e2e/b-colab-prc/101-profile_page_spec.cy.js @@ -1,12 +1,6 @@ /* eslint-disable promise/always-return */ -import { - dashboard, - profile, - manuscripts, - users, - formBuilder, -} from '../../support/routes1' +import { dashboard, profile, manuscripts, users } from '../../support/routes1' import { ProfilePage } from '../../page-object/profile-page' import { Menu } from '../../page-object/page-component/menu' import { DashboardPage } from '../../page-object/dashboard-page' @@ -16,6 +10,7 @@ describe('profile page tests', () => { const restoreUrl = Cypress.config('restoreUrl') cy.request('POST', `${restoreUrl}/commons.colab_bootstrap`) }) + beforeEach(() => { // login and attempt to access the dashboard page cy.fixture('role_names').then(name => { @@ -23,9 +18,11 @@ describe('profile page tests', () => { }) cy.awaitDisappearSpinner() }) + it('first login - users should be asked to add their email', () => { ProfilePage.getPopupEmailField().should('exist').and('be.visible') }) + it('first login - users should not be able to switch pages before adding email', () => { ProfilePage.getPopupEmailField().should('exist').and('be.visible') cy.visit(dashboard) @@ -40,11 +37,8 @@ describe('profile page tests', () => { cy.awaitDisappearSpinner() cy.url().should('not.contain', users).and('contain', profile) ProfilePage.getPopupEmailField().should('exist').and('be.visible') - cy.visit(formBuilder) - cy.awaitDisappearSpinner() - cy.url().should('not.contain', formBuilder).and('contain', profile) - ProfilePage.getPopupEmailField().should('exist').and('be.visible') }) + it('first login - validate email', () => { ProfilePage.updateEmailInPopup('test') ProfilePage.clickPopupNextButton() @@ -59,6 +53,7 @@ describe('profile page tests', () => { ProfilePage.getPopupEmailError().should('be.visible') ProfilePage.getPopupEmailError().should('contain', 'invalid') }) + it('first login - after adding email user can navigate away', () => { ProfilePage.updateEmailInPopup('test@email.com') ProfilePage.clickPopupNextButton() diff --git a/cypress/e2e/b-colab-prc/104-control_page_spec.cy.js b/cypress/e2e/b-colab-prc/104-control_page_spec.cy.js index a7110674a..a3d531353 100644 --- a/cypress/e2e/b-colab-prc/104-control_page_spec.cy.js +++ b/cypress/e2e/b-colab-prc/104-control_page_spec.cy.js @@ -421,6 +421,7 @@ function sendNotification({ ControlPage.getEmailNotificationDropdowns() .eq(1) + .click() .type(`${templateName}{enter}`) } diff --git a/cypress/e2e/b-colab-prc/107-new_manuscript_version_spec.cy.js b/cypress/e2e/b-colab-prc/107-new_manuscript_version_spec.cy.js index 2de549185..1b95f83c3 100644 --- a/cypress/e2e/b-colab-prc/107-new_manuscript_version_spec.cy.js +++ b/cypress/e2e/b-colab-prc/107-new_manuscript_version_spec.cy.js @@ -39,10 +39,9 @@ describe('checking manuscript version', () => { cy.contains('test-pdf.pdf').should('exist') cy.contains('Decision Status').scrollIntoView() // ReviewPage.clickRevise() - cy.get('[data-testid=safe-radio-group] input[value=revise]').click({ - force: true, - }) + ControlPage.clickRevise() /* Submit the decision */ + cy.wait(1000) ControlPage.clickSubmitDecisionButton() /* Check appears in front of button */ ControlPage.checkSvgExists() diff --git a/cypress/e2e/ncrc/300-login_page_spec.cy.js b/cypress/e2e/ncrc/300-login_page_spec.cy.js index 06bf43c77..8269effd2 100644 --- a/cypress/e2e/ncrc/300-login_page_spec.cy.js +++ b/cypress/e2e/ncrc/300-login_page_spec.cy.js @@ -88,7 +88,7 @@ describe('Login page tests', () => { Menu.assertManuscriptsButtonDoesNotExist() Menu.getMyProfileButton().should('be.visible') cy.visit(manuscripts) - cy.contains('404 Page not found.').should('exist') + cy.contains('403').should('exist') cy.awaitDisappearSpinner() ManuscriptsPage.getTableHeader().should('not.exist') ManuscriptsPage.getLiveChatButton().should('not.exist') diff --git a/cypress/page-object/control-page.js b/cypress/page-object/control-page.js index 93c51d4cd..cca6f43b2 100644 --- a/cypress/page-object/control-page.js +++ b/cypress/page-object/control-page.js @@ -110,7 +110,8 @@ export const ControlPage = { return cy.get(DECISION_FIELD).eq(nth) }, fillInDecision(decision) { - this.getDecisionTextInput().click().type(decision, { force: true }) + this.getDecisionTextInput().click() + this.getDecisionTextInput().type(decision, { force: true }) }, getPublishButton() { return cy.get(PUBLISH_BUTTON) @@ -177,7 +178,7 @@ export const ControlPage = { }, getDecisionRadioGroup() { - return cy.get(DECISION_RADIO_BUTTON).should('be.visible') + return cy.get(DECISION_RADIO_BUTTON).scrollIntoView() }, getAcceptRadioButton() { return this.getDecisionRadioGroup().find('input[value="accept"]') @@ -367,7 +368,7 @@ export const ControlPage = { cy.wait(3000) }, getSubmitDecisionButton() { - return cy.getByDataTestId(DECISION_SUBMIT_BUTTON) + return cy.getByDataTestId(DECISION_SUBMIT_BUTTON).scrollIntoView() }, clickSubmitDecisionButton() { this.getSubmitDecisionButton().click() diff --git a/cypress/support/routes1.js b/cypress/support/routes1.js index f7b2718e5..67fef1bec 100644 --- a/cypress/support/routes1.js +++ b/cypress/support/routes1.js @@ -1,7 +1,6 @@ export const login = '/prc/login' export const dashboard = '/prc/dashboard' export const manuscripts = '/prc/admin/manuscripts' -export const formBuilder = '/prc/admin/form-builder' export const reports = '/prc/admin/reports' export const users = '/prc/admin/users' export const profile = '/prc/profile' diff --git a/packages/client/app/components/component-dashboard/src/components/DashboardEditsPage.jsx b/packages/client/app/components/component-dashboard/src/components/DashboardEditsPage.jsx index 5ad192169..8da161414 100644 --- a/packages/client/app/components/component-dashboard/src/components/DashboardEditsPage.jsx +++ b/packages/client/app/components/component-dashboard/src/components/DashboardEditsPage.jsx @@ -3,7 +3,9 @@ import { useMutation, useQuery } from '@apollo/client/react' import { useEffect, useContext } from 'react' import { useLocation } from 'react-router-dom' + import { ConfigContext } from '../../../config/src' +import { useCurrentUser } from '../../../../pages/hooks/useCurrentUser' import { extractFilters, extractSortData, @@ -15,7 +17,6 @@ import { REMOVE_TASK_ALERTS_FOR_CURRENT_USER, DASHBOARD, UPDATE_MANUSCRIPT, - CURRENT_USER, } from '../../../../queries' import EditorTable from './sections/EditorTable' import { CommsErrorBanner, Spinner } from '../../../shared' @@ -25,8 +26,7 @@ const DashboardEditsPage = () => { const config = useContext(ConfigContext) const wantedRoles = ['seniorEditor', 'handlingEditor', 'editor'] - const { data: currentUserData } = useQuery(CURRENT_USER) - const currentUser = currentUserData.currentUser + const currentUser = useCurrentUser() const applyQueryParams = useQueryParams() diff --git a/packages/client/app/components/component-dashboard/src/components/DashboardRedirect.tsx b/packages/client/app/components/component-dashboard/src/components/DashboardRedirect.tsx index 811e7edd4..d0a6b96e4 100644 --- a/packages/client/app/components/component-dashboard/src/components/DashboardRedirect.tsx +++ b/packages/client/app/components/component-dashboard/src/components/DashboardRedirect.tsx @@ -1,15 +1,11 @@ import { type ReactNode } from 'react' import { useParams, Navigate } from 'react-router-dom' -import { useQuery } from '@apollo/client/react' -import { CURRENT_USER } from '../../../../queries' +import { useCurrentUser } from '../../../../pages/hooks/useCurrentUser' const DashboardRedirect = (): ReactNode => { const { groupName } = useParams() - - const { data: currentUserData } = useQuery(CURRENT_USER) - // @ts-ignore - const currentUser = currentUserData.currentUser + const currentUser = useCurrentUser() const invitationId = window.localStorage.getItem('invitationId') || '' const inviteAction = window.localStorage.getItem('inviteAction') || '' diff --git a/packages/client/app/components/component-dashboard/src/components/DashboardReviewsPage.jsx b/packages/client/app/components/component-dashboard/src/components/DashboardReviewsPage.jsx index 0739f3804..9cbebc809 100644 --- a/packages/client/app/components/component-dashboard/src/components/DashboardReviewsPage.jsx +++ b/packages/client/app/components/component-dashboard/src/components/DashboardReviewsPage.jsx @@ -10,8 +10,8 @@ import { UPDATE_TAB, DASHBOARD, UPDATE_MANUSCRIPT, - CURRENT_USER, } from '../../../../queries' +import { useCurrentUser } from '../../../../pages/hooks/useCurrentUser' import { extractFilters, extractSortData, @@ -25,9 +25,7 @@ import { CommsErrorBanner, Spinner } from '../../../shared' const DashboardReviewsPage = () => { const location = useLocation() const config = useContext(ConfigContext) - - const { data: currentUserData } = useQuery(CURRENT_USER) - const currentUser = currentUserData.currentUser + const currentUser = useCurrentUser() const wantedRoles = [ 'reviewer', diff --git a/packages/client/app/components/component-dashboard/src/components/DashboardSubmissionsPage.jsx b/packages/client/app/components/component-dashboard/src/components/DashboardSubmissionsPage.jsx index 688890e38..960ebf194 100644 --- a/packages/client/app/components/component-dashboard/src/components/DashboardSubmissionsPage.jsx +++ b/packages/client/app/components/component-dashboard/src/components/DashboardSubmissionsPage.jsx @@ -10,17 +10,17 @@ import { URI_PAGENUM_PARAM, useQueryParams, } from '../../../../shared/urlParamUtils' -import { CURRENT_USER, UPDATE_TAB, DASHBOARD } from '../../../../queries' +import { UPDATE_TAB, DASHBOARD } from '../../../../queries' import SubmissionsTable from './sections/SubmissionsTable' import { CommsErrorBanner, Spinner } from '../../../shared' +import { useCurrentUser } from '../../../../pages/hooks/useCurrentUser' const DashboardSubmissionsPage = () => { const location = useLocation() const config = useContext(ConfigContext) const wantedRoles = ['author'] - const { data: currentUserData } = useQuery(CURRENT_USER) - const currentUser = currentUserData.currentUser + const currentUser = useCurrentUser() const applyQueryParams = useQueryParams() diff --git a/packages/client/app/components/component-manuscript/src/components/ManuscriptPage.jsx b/packages/client/app/components/component-manuscript/src/components/ManuscriptPage.jsx index 079cfc281..c05e12f7b 100644 --- a/packages/client/app/components/component-manuscript/src/components/ManuscriptPage.jsx +++ b/packages/client/app/components/component-manuscript/src/components/ManuscriptPage.jsx @@ -1,23 +1,21 @@ import { useParams } from 'react-router-dom' import { useQuery } from '@apollo/client/react' + import Manuscript from './Manuscript' import { Spinner, CommsErrorBanner } from '../../../shared' -import { - MANUSCRIPT_FOR_MANUSCRIPT_PAGE, - CURRENT_USER, -} from '../../../../queries' +import { MANUSCRIPT_FOR_MANUSCRIPT_PAGE } from '../../../../queries' +import { useCurrentUser } from '../../../../pages/hooks/useCurrentUser' const ManuscriptPage = () => { const params = useParams() + const currentUser = useCurrentUser() + const { data, loading, error } = useQuery(MANUSCRIPT_FOR_MANUSCRIPT_PAGE, { variables: { id: params.version, }, }) - const { data: currentUserData } = useQuery(CURRENT_USER) - const currentUser = currentUserData.currentUser - if (loading) return if (error) return const { manuscript } = data diff --git a/packages/client/app/components/component-manuscripts/src/ManuscriptsPage.jsx b/packages/client/app/components/component-manuscripts/src/ManuscriptsPage.jsx index 1db210c10..6f8451ae4 100644 --- a/packages/client/app/components/component-manuscripts/src/ManuscriptsPage.jsx +++ b/packages/client/app/components/component-manuscripts/src/ManuscriptsPage.jsx @@ -29,7 +29,6 @@ import { PUBLISH_MANUSCRIPT, EXPAND_CHAT, UPDATE_MANUSCRIPT, - CURRENT_USER, } from '../../../queries' import Manuscripts from './Manuscripts' import { @@ -41,17 +40,18 @@ import { } from '../../../shared/urlParamUtils' import { validateDoi, validateSuffix } from '../../../shared/commsUtils' import useChat from '../../../hooks/useChat' +import { useCurrentUser } from '../../../pages/hooks/useCurrentUser' const ManuscriptsPage = () => { const location = useLocation() const { t } = useTranslation() - const [doUpdateManuscript] = useMutation(UPDATE_MANUSCRIPT) + const currentUser = useCurrentUser() + const config = useContext(ConfigContext) const { urlFrag } = config const chatRoomId = fnv.hash(config.clientUrl).hex() - const { data: currentUserData } = useQuery(CURRENT_USER) - const currentUser = currentUserData.currentUser + const [doUpdateManuscript] = useMutation(UPDATE_MANUSCRIPT) /** Returns an array of column names, e.g. * ['shortId', 'created', 'titleAndAbstract', 'submission.topic', 'status'] */ diff --git a/packages/client/app/components/component-production/src/components/ProductionPage.jsx b/packages/client/app/components/component-production/src/components/ProductionPage.jsx index efea40fcd..67650c751 100644 --- a/packages/client/app/components/component-production/src/components/ProductionPage.jsx +++ b/packages/client/app/components/component-production/src/components/ProductionPage.jsx @@ -11,6 +11,7 @@ import ModalContext from '../../../asset-manager/src/ui/Modal/ModalContext' import DownloadPdfComponent from './DownloadPdf' import DownloadJatsComponent from './DownloadJats' import { waxAiToolSystem } from '../../helpers' +import { useCurrentUser } from '../../../../pages/hooks/useCurrentUser' import { GET_SPECIFIC_FILES, @@ -19,7 +20,6 @@ import { PRODUCTION_MANUSCRIPT_UPDATE, SUBMIT_AUTHOR_PROOFING_FEEDBACK, UPDATE_TEMPLATE, - CURRENT_USER, } from '../../../../queries' const showAuthorProofingMode = ( @@ -51,6 +51,7 @@ const showAuthorProofingMode = ( const ProductionPage = () => { const params = useParams() + const currentUser = useCurrentUser() const { groupId, controlPanel, submission } = useContext(ConfigContext) const client = useApolloClient() const { @@ -118,9 +119,6 @@ const ProductionPage = () => { // }, }) - const { data: currentUserData } = useQuery(CURRENT_USER) - const currentUser = currentUserData.currentUser - const [update] = useMutation(PRODUCTION_MANUSCRIPT_UPDATE) const [submitAuthorProofingFeedback] = useMutation( diff --git a/packages/client/app/components/component-profile/src/ProfilePage.jsx b/packages/client/app/components/component-profile/src/ProfilePage.jsx index 9de547ef2..52e43ca0e 100644 --- a/packages/client/app/components/component-profile/src/ProfilePage.jsx +++ b/packages/client/app/components/component-profile/src/ProfilePage.jsx @@ -12,6 +12,7 @@ import { Spinner, CommsErrorBanner } from '../../shared' import packageJson from '../../../../package.json' import { ConfigContext } from '../../config/src' +import { useCurrentUser } from '../../../pages/hooks/useCurrentUser' import { GET_USER, @@ -20,22 +21,16 @@ import { UPDATE_LANGUAGE, GET_GLOBAL_CHAT_NOTIFICATION_OPTION, UPDATE_GLOBAL_CHAT_NOTIFICATION_OPTION, - CURRENT_USER, } from '../../../queries' const { version: kotahiVersion } = packageJson const ProfilePage = () => { const { id } = useParams() - + const currentUser = useCurrentUser() const { urlFrag } = useContext(ConfigContext) const [didLogout, setDidLogout] = useState(false) - const { data: currentUserData, loading: currentUserLoading } = - useQuery(CURRENT_USER) - - const currentUser = currentUserData?.currentUser - const { loading, error, @@ -75,7 +70,7 @@ const ProfilePage = () => { }) } - if (loading || currentUserLoading) return + if (loading) return if (error) return if (didLogout) { diff --git a/packages/client/app/components/component-review/src/components/DecisionPage.jsx b/packages/client/app/components/component-review/src/components/DecisionPage.jsx index 2fa15c1d2..08950c73b 100644 --- a/packages/client/app/components/component-review/src/components/DecisionPage.jsx +++ b/packages/client/app/components/component-review/src/components/DecisionPage.jsx @@ -18,6 +18,7 @@ import { AccessErrorPage, CommsErrorBanner, Spinner } from '../../../shared' import DecisionVersions from './DecisionVersions' import { roles } from '../../../../globals' import { waxAiToolSystem } from '../../../component-production/helpers' +import { useCurrentUser } from '../../../../pages/hooks/useCurrentUser' import { ADD_REVIEWER, @@ -57,8 +58,8 @@ import { REVIEW_FORM_UPDATED, NEW_REVIEW_FRAGMENT, NEW_TEAM_FRAGMENT, + CREATED_TEAM_FRAGMENT, UPDATE_ADA, - CURRENT_USER, } from '../../../../queries' import { validateDoi, validateSuffix } from '../../../../shared/commsUtils' @@ -85,8 +86,7 @@ const DecisionPage = () => { skip: true, }) - const { data: currentUserData } = useQuery(CURRENT_USER) - const currentUser = currentUserData.currentUser + const currentUser = useCurrentUser() useEffect(() => { return () => { @@ -107,7 +107,6 @@ const DecisionPage = () => { const { loading, data: currentData, - previousData, error, refetch: refetchManuscript, } = useQuery(MANUSCRIPT_FOR_REVIEW, { @@ -116,7 +115,8 @@ const DecisionPage = () => { groupId: config.groupId, }, }) - const data = currentData ?? previousData + + const data = currentData let editorialChannel, allChannel @@ -192,7 +192,22 @@ const DecisionPage = () => { const [makeDecision] = useMutation(MAKE_DECISION) const [publishManuscript] = useMutation(PUBLISH_MANUSCRIPT) const [updateTeam] = useMutation(UPDATE_TEAM) - const [createTeam] = useMutation(CREATE_TEAM) + const [createTeam] = useMutation(CREATE_TEAM, { + update(cache, { data: { createTeam: newTeam } }) { + cache.modify({ + id: cache.identify({ __typename: 'Manuscript', id: newTeam.objectId }), + fields: { + teams: existingRefs => { + const ref = cache.writeFragment({ + data: newTeam, + fragment: CREATED_TEAM_FRAGMENT, + }) + return [...existingRefs, ref] + }, + }, + }) + }, + }) const [updateTeamMember] = useMutation(UPDATE_TEAM_MEMBER) const [updateCollaborativeTeamMember] = useMutation( @@ -354,7 +369,9 @@ const DecisionPage = () => { const [refreshAdaStatus] = useMutation(REFRESH_ADA_STATUS) // Count In the Collaborative Reviews and choose the correct one. - const currentUserReview = getCurrentUserReview(data?.manuscript, currentUser) + const currentUserReview = currentUser + ? getCurrentUserReview(data?.manuscript, currentUser) + : {} useSubscription(REVIEW_FORM_UPDATED, { variables: { @@ -422,7 +439,7 @@ const DecisionPage = () => { }) } - if (loading && !data) return + if ((loading && !data) || !currentUser) return if (error) { if (error.graphQLErrors?.find(e => e.message === 'Not Authorised!')) { @@ -554,10 +571,7 @@ const DecisionPage = () => { } const handleCreateTeam = async createTeamVariables => { - const createTeamResponse = await createTeam(createTeamVariables) - await refetchData() - - return createTeamResponse + return await createTeam(createTeamVariables) } const sendChannelMessage = async messageData => { diff --git a/packages/client/app/components/component-review/src/components/DecisionVersion.jsx b/packages/client/app/components/component-review/src/components/DecisionVersion.jsx index 640275fc4..b8965a2d9 100644 --- a/packages/client/app/components/component-review/src/components/DecisionVersion.jsx +++ b/packages/client/app/components/component-review/src/components/DecisionVersion.jsx @@ -91,7 +91,7 @@ const DecisionVersion = ({ selectedEmailIsBlacklisted, updateSharedStatusForInvitedReviewer, dois, - refetch, + // refetch, updateTask, updateTasks, // teams, @@ -709,7 +709,6 @@ const DecisionVersion = ({ defaultActiveKey={locationState} onChange={key => { navigate(`?tab=${key}`, { replace: true }) - refetch() }} sections={sections} /> diff --git a/packages/client/app/components/component-review/src/components/ReviewPage.jsx b/packages/client/app/components/component-review/src/components/ReviewPage.jsx index 44d0f9e46..b2fefc352 100644 --- a/packages/client/app/components/component-review/src/components/ReviewPage.jsx +++ b/packages/client/app/components/component-review/src/components/ReviewPage.jsx @@ -19,22 +19,20 @@ import { MANUSCRIPT, EXPAND_CHAT, REVIEW_FORM_UPDATED, - CURRENT_USER, } from '../../../../queries' import useChat from '../../../../hooks/useChat' +import { useCurrentUser } from '../../../../pages/hooks/useCurrentUser' import { getCurrentUserReview } from './review/util' const ReviewPage = () => { const params = useParams() const { t } = useTranslation() - const config = useContext(ConfigContext) + const currentUser = useCurrentUser() + const config = useContext(ConfigContext) const { urlFrag } = config - const { data: currentUserData } = useQuery(CURRENT_USER) - const currentUser = currentUserData.currentUser - const [updateReviewMutation] = useMutation(UPDATE_REVIEW) const [updateReviewerStatus] = useMutation(UPDATE_REVIEWER_STATUS) const [createFile] = useMutation(CREATE_FILE) diff --git a/packages/client/app/components/component-submit/src/components/NewSubmissionPage.jsx b/packages/client/app/components/component-submit/src/components/NewSubmissionPage.jsx index f54a7eeac..5a5aee045 100644 --- a/packages/client/app/components/component-submit/src/components/NewSubmissionPage.jsx +++ b/packages/client/app/components/component-submit/src/components/NewSubmissionPage.jsx @@ -1,11 +1,11 @@ import { useContext } from 'react' import PropTypes from 'prop-types' -import { useApolloClient, useQuery } from '@apollo/client/react' +import { useApolloClient } from '@apollo/client/react' import { useTranslation } from 'react-i18next' import { Container, Content, UploadContainer, Heading } from '../style' import UploadManuscript from './UploadManuscript' import { ConfigContext } from '../../../config/src' -import { CURRENT_USER } from '../../../../queries' +import { useCurrentUser } from '../../../../pages/hooks/useCurrentUser' const acceptUploadFiles = [ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', @@ -29,11 +29,7 @@ const acceptFiles = const Dashboard = () => { const client = useApolloClient() const { t } = useTranslation() - - const { data: currentUserData } = useQuery(CURRENT_USER) - - // @ts-ignore - const currentUser = currentUserData.currentUser + const currentUser = useCurrentUser() const { submission: { submissionPage }, diff --git a/packages/client/app/components/component-submit/src/components/SubmitPage.jsx b/packages/client/app/components/component-submit/src/components/SubmitPage.jsx index 1fc05f54a..06c1fdc0f 100644 --- a/packages/client/app/components/component-submit/src/components/SubmitPage.jsx +++ b/packages/client/app/components/component-submit/src/components/SubmitPage.jsx @@ -11,6 +11,7 @@ import { validateManuscriptSubmission } from '../../../../shared/manuscriptUtils import CommsErrorBanner from '../../../shared/CommsErrorBanner' import { validateDoi, validateSuffix } from '../../../../shared/commsUtils' import useChat from '../../../../hooks/useChat' +import { useCurrentUser } from '../../../../pages/hooks/useCurrentUser' import { PUBLISH_MANUSCRIPT, SET_SHOULD_PUBLISH_FIELD, @@ -26,7 +27,6 @@ import { CREATE_NEW_MANUSCRIPT_VERSION, CREATE_FILE, DELETE_FILE, - CURRENT_USER, } from '../../../../queries' let debouncers = {} @@ -51,7 +51,7 @@ const SubmitPage = () => { const navigate = useNavigate() const params = useParams() const location = useLocation() - + const currentUser = useCurrentUser() const { t } = useTranslation() const config = useContext(ConfigContext) const { urlFrag, instanceName } = config @@ -69,9 +69,6 @@ const SubmitPage = () => { const decisionPurpose = 'decision' const reviewPurpose = 'review' - const { data: currentUserData } = useQuery(CURRENT_USER) - const currentUser = currentUserData.currentUser - const { data, loading, error } = useQuery( USER_MANUSCRIPT, { diff --git a/packages/client/app/components/component-users-manager/src/UsersPage.jsx b/packages/client/app/components/component-users-manager/src/UsersPage.jsx index 6a0f24de9..247c1c79e 100644 --- a/packages/client/app/components/component-users-manager/src/UsersPage.jsx +++ b/packages/client/app/components/component-users-manager/src/UsersPage.jsx @@ -8,13 +8,13 @@ import { useQueryParams, } from '../../../shared/urlParamUtils' import UsersTable from './UsersTable' +import { useCurrentUser } from '../../../pages/hooks/useCurrentUser' import { GET_USERS, DELETE_USER, SET_GROUP_ROLE, SET_GLOBAL_ROLE, - CURRENT_USER, } from '../../../queries' const defaultSortDirections = { @@ -27,9 +27,7 @@ const defaultSortDirections = { const UsersPage = () => { const location = useLocation() const applyQueryParams = useQueryParams() - - const { data: currentUserData } = useQuery(CURRENT_USER) - const currentUser = currentUserData.currentUser + const currentUser = useCurrentUser() const params = new URLSearchParams(location.search) const page = params.get(URI_PAGENUM_PARAM) || 1 diff --git a/packages/client/app/pages/Authenticated.page.tsx b/packages/client/app/pages/Authenticated.page.tsx index 926a1085e..dd1fb3231 100644 --- a/packages/client/app/pages/Authenticated.page.tsx +++ b/packages/client/app/pages/Authenticated.page.tsx @@ -10,6 +10,7 @@ import { Spinner } from '../components/shared' import { JournalContext } from '../components/xpub-journal' import { ConfigContext } from '../components/config/src' import { getLanguages } from '../i18n' +import { CurrentUserContext } from './hooks/useCurrentUser' const AuthenticatedPage = (): ReactNode => { const { pathname } = useLocation() @@ -74,7 +75,11 @@ const AuthenticatedPage = (): ReactNode => { return } - return + return ( + + + + ) } export default AuthenticatedPage diff --git a/packages/client/app/pages/hooks/useCurrentUser.tsx b/packages/client/app/pages/hooks/useCurrentUser.tsx new file mode 100644 index 000000000..9cc0d030e --- /dev/null +++ b/packages/client/app/pages/hooks/useCurrentUser.tsx @@ -0,0 +1,15 @@ +import { createContext, useContext } from 'react' + +type CurrentUser = { id: string /* ... */ } + +export const CurrentUserContext = createContext(null) + +/* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */ +export const useCurrentUser = () => { + const user = useContext(CurrentUserContext) + + if (!user) + throw new Error('useCurrentUser must be used inside AuthenticatedPage') + + return user +} diff --git a/packages/client/app/queries/team.queries.ts b/packages/client/app/queries/team.queries.ts index d1c1f2586..d95cae70c 100644 --- a/packages/client/app/queries/team.queries.ts +++ b/packages/client/app/queries/team.queries.ts @@ -18,8 +18,10 @@ const teamFields = ` user { id username + email defaultIdentity { id + name identifier } profilePicture @@ -173,3 +175,31 @@ export const NEW_TEAM_FRAGMENT = gql` } } ` + +export const CREATED_TEAM_FRAGMENT = gql` + fragment CreatedTeam on Team { + id + displayName + role + objectId + objectType + members { + id + updated + status + isShared + user { + id + username + email + defaultIdentity { + id + name + identifier + } + profilePicture + isOnline + } + } + } +` From 897e2a33565548c5c924278f6c9ab5fc7701120c Mon Sep 17 00:00:00 2001 From: yannis Date: Mon, 22 Jun 2026 15:49:17 +0300 Subject: [PATCH 12/16] test(*): more test fixes --- cypress/e2e/a-journal/005-decision_spec.cy.js | 2 +- cypress/e2e/b-colab-prc/104-control_page_spec.cy.js | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cypress/e2e/a-journal/005-decision_spec.cy.js b/cypress/e2e/a-journal/005-decision_spec.cy.js index 3d805befb..dceaa9838 100644 --- a/cypress/e2e/a-journal/005-decision_spec.cy.js +++ b/cypress/e2e/a-journal/005-decision_spec.cy.js @@ -98,7 +98,7 @@ describe('Completing a decision', () => { cy.wait(1000) ControlPage.clickAccept() - cy.wait(1000) + cy.wait(2000) ControlPage.clickSubmitDecisionButton() // Submit the decision ControlPage.checkSvgExists() // The below should be fixed by #1872 !!! diff --git a/cypress/e2e/b-colab-prc/104-control_page_spec.cy.js b/cypress/e2e/b-colab-prc/104-control_page_spec.cy.js index a3d531353..bea358245 100644 --- a/cypress/e2e/b-colab-prc/104-control_page_spec.cy.js +++ b/cypress/e2e/b-colab-prc/104-control_page_spec.cy.js @@ -409,7 +409,9 @@ function sendNotification({ ControlPage.getEmailNotificationDropdowns() .eq(2) - .type(`${templateName}{enter}`) + .click() + .find('input') + .type(`${templateName}{enter}`, { force: true }) } else { cy.getByDataTestId('choose-receiver').click() cy.get('input[aria-label="Choose receiver"]').type( @@ -422,7 +424,8 @@ function sendNotification({ ControlPage.getEmailNotificationDropdowns() .eq(1) .click() - .type(`${templateName}{enter}`) + .find('input') + .type(`${templateName}{enter}`, { force: true }) } cy.contains('Notify').click() From 739267c3da7a00035c7c91f65117ce594a7b5b84 Mon Sep 17 00:00:00 2001 From: yannis Date: Mon, 6 Jul 2026 13:20:11 +0300 Subject: [PATCH 13/16] fix(ui): fix new coar route --- packages/client/app/pages/Menu.page.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/client/app/pages/Menu.page.tsx b/packages/client/app/pages/Menu.page.tsx index ed1b16941..55307f713 100644 --- a/packages/client/app/pages/Menu.page.tsx +++ b/packages/client/app/pages/Menu.page.tsx @@ -75,6 +75,7 @@ const MenuPage = (): ReactNode => { const profileLink = `${urlFrag}/profile` const reportsLink = `${urlFrag}/admin/reports` const homeLink = `${urlFrag}/dashboard` + const coarNotifyLink = `${urlFrag}/admin/coar-inbox` const showLinks = location.pathname.match(/^\/(submit|manuscript)/g) @@ -118,12 +119,21 @@ const MenuPage = (): ReactNode => { name: t('leftMenu.Manuscripts'), icon: 'file-text', }) + if (config?.report?.showInMenu && isGroupAdmin) links.push({ link: reportsLink, name: t('leftMenu.Reports'), icon: 'activity', }) + + if (config?.controlPanel?.showTabs.includes('COAR Notify Metadata')) { + links.push({ + link: coarNotifyLink, + name: t('leftMenu.CoarNotifyInbox'), + icon: '_coar-notify', + }) + } } if (isGroupAdmin || isAdmin) { From 2a7276d272fef3903c6378f71e65bb5d06a00114 Mon Sep 17 00:00:00 2001 From: yannis Date: Mon, 6 Jul 2026 13:53:38 +0300 Subject: [PATCH 14/16] fix(ui): edit coar icon to make it consistent with theme --- .../app/components/component-menu/styles/menuStyleds.jsx | 9 +++++++++ packages/client/app/components/shared/Icons.jsx | 7 +++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/client/app/components/component-menu/styles/menuStyleds.jsx b/packages/client/app/components/component-menu/styles/menuStyleds.jsx index 459c389df..f8da5a0e0 100644 --- a/packages/client/app/components/component-menu/styles/menuStyleds.jsx +++ b/packages/client/app/components/component-menu/styles/menuStyleds.jsx @@ -150,6 +150,11 @@ export const StyledLink = styled(Link)` width: 1em; } + svg#coar { + color: ${p => (p.$active ? color.text : color.textReverse)}; + transition: color var(--transition-time); + } + &:hover { background-color: ${color.brand1.tint70}; color: ${color.text} !important; @@ -158,6 +163,10 @@ export const StyledLink = styled(Link)` svg { stroke: ${color.text}; } + + svg#coar { + color: ${color.text}; + } } ` diff --git a/packages/client/app/components/shared/Icons.jsx b/packages/client/app/components/shared/Icons.jsx index 2e7a8e239..5963cb61e 100644 --- a/packages/client/app/components/shared/Icons.jsx +++ b/packages/client/app/components/shared/Icons.jsx @@ -82,20 +82,23 @@ export const CoarIcon = ({ className, height, width }) => { ) From 36670deac54c846ef38b2e4f4caf63755d04a6eb Mon Sep 17 00:00:00 2001 From: Vukile Langa Date: Mon, 6 Jul 2026 18:02:35 +0200 Subject: [PATCH 15/16] refactor(client): renamed default page to remove apfs ambiguity --- packages/client/app/{Pages.jsx => DefaultPage.jsx} | 4 ++-- packages/client/app/start.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename packages/client/app/{Pages.jsx => DefaultPage.jsx} (94%) diff --git a/packages/client/app/Pages.jsx b/packages/client/app/DefaultPage.jsx similarity index 94% rename from packages/client/app/Pages.jsx rename to packages/client/app/DefaultPage.jsx index aca91483a..8c248003d 100644 --- a/packages/client/app/Pages.jsx +++ b/packages/client/app/DefaultPage.jsx @@ -16,7 +16,7 @@ const modals = { assetManagerEditor: AssetManager, } -const Pages = () => { +const DefaultPage = () => { Modal.setAppElement('#root') return ( @@ -33,4 +33,4 @@ const Pages = () => { ) } -export default +export default diff --git a/packages/client/app/start.js b/packages/client/app/start.js index 8fad93e58..8f6db4927 100644 --- a/packages/client/app/start.js +++ b/packages/client/app/start.js @@ -4,7 +4,7 @@ import { setContext } from '@apollo/client/link/context' import { startClient } from '@coko/client' import theme from './theme' -import routes from './Pages' +import routes from './DefaultPage' import './i18n' From fd9a5a565f50d8d90e7f661a7bf452e29159372b Mon Sep 17 00:00:00 2001 From: yannis Date: Tue, 7 Jul 2026 10:44:46 +0300 Subject: [PATCH 16/16] fix(ui): keep semantic scholar svg color consistent with coar --- packages/client/app/components/shared/Icons.jsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/client/app/components/shared/Icons.jsx b/packages/client/app/components/shared/Icons.jsx index 5963cb61e..3ff3945e5 100644 --- a/packages/client/app/components/shared/Icons.jsx +++ b/packages/client/app/components/shared/Icons.jsx @@ -27,6 +27,10 @@ export const DragVerticalIcon = ({ ) } +/** + * Keep original colors commented out because it will be a pain to find them if + * we ever decice to revert. + */ export const SemanticScholarIcon = ({ className, height, width }) => { return ( { )