diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts index 98d5e703..2c12a241 100644 --- a/cypress/support/e2e.ts +++ b/cypress/support/e2e.ts @@ -44,7 +44,7 @@ declare global { targetSelector: string, ): Chainable; loadLandingPage(): Chainable; - removeWidget(widgetId: string): void; + removeWidget(widgetId: string): Chainable; } } } diff --git a/package.json b/package.json index fdd00452..2c904ab1 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,6 @@ "cypress:run:cp": "cypress run --component", "fixjs": "eslint src cypress --fix", "lint": "eslint src cypress .storybook", - "nightly": "npm-run-all build lint && npm run test -- -u", "postinstall": "ts-patch install && rm -rf .cache", "start": "fec dev", "static": "fec static", diff --git a/src/App.tsx b/src/App.tsx index b43b8575..8c9cf0da 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,82 +1,33 @@ -import React, { - Suspense, - createContext, - lazy, - useEffect, - useState, -} from 'react'; -import '@patternfly/patternfly/utilities/Text/text.css'; -import { Route, Routes } from 'react-router-dom'; +import React, { Suspense } from 'react'; import useChrome from '@redhat-cloud-services/frontend-components/useChrome'; import { Bullseye } from '@patternfly/react-core/dist/dynamic/layouts/Bullseye'; import { Spinner } from '@patternfly/react-core/dist/dynamic/components/Spinner'; -import { useNavigate } from 'react-router-dom'; -import NotificationsProvider from '@redhat-cloud-services/frontend-components-notifications/NotificationsProvider'; - -const Landing = lazy( - () => import(/* webpackCunkName: "Landing" */ './routes/Landing'), -); -const Maintenance = lazy( - () => import(/* webpackCunkName: "Maintenance" */ './routes/Maintenance'), -); -const NotFound = lazy( - () => import(/* webpackCunkName: "NotFound" */ './routes/404'), -); - -const routes = { - landing: '/', - maintenance: '/maintenance', -}; +import '@patternfly/patternfly/utilities/Text/text.css'; -export const PermissionContext = createContext<{ - isOrgAdmin?: boolean; -}>({}); +import Landing from './routes/Landing'; +/** + * The module chrome mounts at exactly `/` (CRD: app `landing`, module + * `./RootApp`, route `/` exact). Chrome owns routing: any location change + * away from `/` stops matching chrome's route for this app and unmounts + * it — there is nothing to route to in here. The app's entire job is the + * Landing composition that mounts widgetLayout's layout engine. + */ const App: React.FC<{ layoutType?: string }> = ({ layoutType }) => { - const [isOrgAdmin, setIsOrgAdmin] = useState(false); const chrome = useChrome(); - const navigate = useNavigate(); - const { on } = useChrome(); chrome?.updateDocumentTitle?.('Hybrid Cloud Console Home', false); - useEffect(() => { - chrome.auth - .getUser() - .then( - (user) => user && setIsOrgAdmin(!!user?.identity?.user?.is_org_admin), - ); - }, []); - - useEffect(() => { - const unregister = on('APP_NAVIGATION', (event) => - navigate(`/${event.navId}`), - ); - return () => { - unregister?.(); - }; - }, []); - return ( - - - - - - } - > - - } - /> - } /> - } /> - - - + + + + } + > + + ); }; diff --git a/src/components/__tests__/__snapshots__/icon-404.test.tsx.snap b/src/components/__tests__/__snapshots__/icon-404.test.tsx.snap deleted file mode 100644 index 93e22f53..00000000 --- a/src/components/__tests__/__snapshots__/icon-404.test.tsx.snap +++ /dev/null @@ -1,244 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`404 component > should render correctly 1`] = ` -
- - - - - - - - - - - - 404path-not-found - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-`; diff --git a/src/components/__tests__/icon-404.test.tsx b/src/components/__tests__/icon-404.test.tsx deleted file mode 100644 index 86d371c2..00000000 --- a/src/components/__tests__/icon-404.test.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import { render } from '@testing-library/react'; -import Icon404 from '../icon-404'; - -describe('404 component', () => { - it('should render correctly', () => { - const { container } = render(); - expect(container).toMatchSnapshot(); - }); -}); diff --git a/src/components/icon-404.scss b/src/components/icon-404.scss deleted file mode 100644 index 85fd9884..00000000 --- a/src/components/icon-404.scss +++ /dev/null @@ -1,11 +0,0 @@ -.Icon404 { - height: 150px; - - .cls-1 { fill:#fff; } - - .cls-1,.cls-3{ fill-rule:evenodd;} - - .cls-2{ opacity:0.5;} - - .cls-4{ mask:url(#mask); } -} \ No newline at end of file diff --git a/src/components/icon-404.stories.tsx b/src/components/icon-404.stories.tsx deleted file mode 100644 index dedcdef0..00000000 --- a/src/components/icon-404.stories.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react-vite'; -import { expect, within } from 'storybook/test'; - -import Icon404 from './icon-404'; - -const meta: Meta = { - title: 'Components/Icon404', - component: Icon404, -}; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - play: async ({ canvasElement }) => { - const canvas = within(canvasElement); - await expect( - canvasElement.querySelector('svg#Icon404'), - ).toBeInTheDocument(); - await expect(canvas.getByTitle('404path-not-found')).toBeInTheDocument(); - }, -}; diff --git a/src/components/icon-404.tsx b/src/components/icon-404.tsx deleted file mode 100644 index 6450941d..00000000 --- a/src/components/icon-404.tsx +++ /dev/null @@ -1,225 +0,0 @@ -import React from 'react'; - -import './icon-404.scss'; -const Icon404 = () => ( - - - - - - - - - - - 404path-not-found - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -); - -export default Icon404; diff --git a/src/components/icon-hourglass.scss b/src/components/icon-hourglass.scss deleted file mode 100644 index ae69f5fd..00000000 --- a/src/components/icon-hourglass.scss +++ /dev/null @@ -1,8 +0,0 @@ -.IconHourglass { - .st0{fill:none;} - .st1{fill:#E80000;} - .st2{fill:none;stroke:#E80000;stroke-width:2.134;stroke-linejoin:round;stroke-miterlimit:10;} - .st3{fill:#FFFFFF;stroke:#E80000;stroke-width:2.134;stroke-miterlimit:10;} - .st4{fill:url(#SVGID_1_);stroke:#E80000;stroke-width:2.134;stroke-miterlimit:10;} - .st5{fill:url(#SVGID_2_);stroke:#E80000;stroke-width:2.134;stroke-linejoin:round;stroke-miterlimit:10;} -} \ No newline at end of file diff --git a/src/components/icon-hourglass.stories.tsx b/src/components/icon-hourglass.stories.tsx deleted file mode 100644 index e633097e..00000000 --- a/src/components/icon-hourglass.stories.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react-vite'; -import { expect } from 'storybook/test'; - -import IconHourglass from './icon-hourglass'; - -const meta: Meta = { - title: 'Components/IconHourglass', - component: IconHourglass, -}; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - play: async ({ canvasElement }) => { - await expect( - canvasElement.querySelector('svg.IconHourglass'), - ).toBeInTheDocument(); - }, -}; diff --git a/src/components/icon-hourglass.tsx b/src/components/icon-hourglass.tsx deleted file mode 100644 index a74cc647..00000000 --- a/src/components/icon-hourglass.tsx +++ /dev/null @@ -1,145 +0,0 @@ -import React from 'react'; - -import './icon-hourglass.scss'; -const IconHourglass = () => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -); - -export default IconHourglass; diff --git a/src/components/recently-visited/recently-visited.tsx b/src/components/recently-visited/recently-visited.tsx deleted file mode 100644 index fededdba..00000000 --- a/src/components/recently-visited/recently-visited.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { - Content, - ContentVariants, -} from '@patternfly/react-core/dist/dynamic/components/Content'; -import React, { Fragment } from 'react'; -import { useLastVisited } from '@redhat-cloud-services/chrome'; -import useChrome from '@redhat-cloud-services/frontend-components/useChrome'; -import { Link } from 'react-router-dom'; - -const LinkWrapper = ({ - pathname, - title, -}: { - pathname: string; - title: string; -}) => { - const { updateDocumentTitle } = useChrome(); - return ( - updateDocumentTitle(title)} to={pathname}> - {title} - - ); -}; - -const RecentlyVisited = () => { - const lastVisited = useLastVisited(); - const lastVisitedData = lastVisited.slice(0, 10); - return ( - - - Recently visited - - {lastVisitedData.map(({ bundle, pathname, title }, index) => ( - - - {bundle} - - ))} - - ); -}; - -export default RecentlyVisited; diff --git a/src/components/useCurrentUser.ts b/src/components/useCurrentUser.ts deleted file mode 100644 index bb555066..00000000 --- a/src/components/useCurrentUser.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { useState } from 'react'; -import useLoaded from './useLoaded'; -import useChrome from '@redhat-cloud-services/frontend-components/useChrome'; -import { ChromeUser } from '@redhat-cloud-services/types'; - -const useCurrentUser = () => { - const [currentUser, setCurrentUser] = - useState(undefined); - const chrome = useChrome(); - - const isLoaded = useLoaded(async () => { - const user = await chrome.auth.getUser(); - if (user) { - setCurrentUser(user.identity.user); - } - }); - - return { - isLoaded, - currentUser, - }; -}; - -export default useCurrentUser; diff --git a/src/components/useLoaded.ts b/src/components/useLoaded.ts deleted file mode 100644 index 3f2626dc..00000000 --- a/src/components/useLoaded.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { useEffect, useState } from 'react'; - -const useLoaded = (loader: () => Promise) => { - const [isLoaded, setLoaded] = useState(false); - useEffect(() => { - (async () => { - await loader(); - setLoaded(true); - })(); - }, []); - - return isLoaded; -}; - -export default useLoaded; diff --git a/src/moduleEntries/AppEntry.tsx b/src/moduleEntries/AppEntry.tsx index 677984ef..84d9292a 100644 --- a/src/moduleEntries/AppEntry.tsx +++ b/src/moduleEntries/AppEntry.tsx @@ -1,9 +1,6 @@ import React from 'react'; import App from '../App'; -const pathName = window.location.pathname.split('/'); -pathName.shift(); - const AppRoot: React.FC<{ layoutType?: string }> = ({ layoutType }) => ( ); diff --git a/src/routes/404.scss b/src/routes/404.scss deleted file mode 100644 index 37ca102e..00000000 --- a/src/routes/404.scss +++ /dev/null @@ -1,15 +0,0 @@ -@use '@redhat-cloud-services/frontend-components-utilities/styles/mixins' as *; - -.land-c-page__404 { - display: flex; - justify-content: center; - flex-direction: column; - align-items: center; - text-align: center; - - .land-c-text__sorry { max-width: 70%; } - - h1, svg { @include rem('margin-bottom', 30px); } - - a { @include rem('font-size', 20px); } -} \ No newline at end of file diff --git a/src/routes/404.stories.tsx b/src/routes/404.stories.tsx deleted file mode 100644 index 7ca67aeb..00000000 --- a/src/routes/404.stories.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react-vite'; -import { expect, within } from 'storybook/test'; - -import NotFound from './404'; - -const meta: Meta = { - title: 'Routes/404', - component: NotFound, -}; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - play: async ({ canvasElement }) => { - const canvas = within(canvasElement); - await expect( - canvas.getByRole('heading', { name: '404: We lost that page' }), - ).toBeInTheDocument(); - await expect( - canvas.getByRole('heading', { name: /Let's find you a new one/ }), - ).toBeInTheDocument(); - await expect( - canvas.getByRole('link', { name: 'Return to homepage' }), - ).toBeInTheDocument(); - }, -}; diff --git a/src/routes/404.tsx b/src/routes/404.tsx deleted file mode 100644 index 2e4c24bd..00000000 --- a/src/routes/404.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import { Button } from '@patternfly/react-core/dist/dynamic/components/Button'; -import { Title } from '@patternfly/react-core/dist/dynamic/components/Title'; -import Icon404 from '../components/icon-404'; - -import './404.scss'; - -// Chrome is not on this page, so do the isBeta here -const isBeta = () => { - return window.location.pathname.split('/')[1] === 'beta' ? '/beta' : ''; -}; - -const NotFound = () => ( -
-
- - 404: We lost that page - - - - Let's find you a new one. Try a new search or return home. - - -
-
-); - -export default NotFound; diff --git a/src/routes/Logout.scss b/src/routes/Logout.scss deleted file mode 100644 index 3b7e80a3..00000000 --- a/src/routes/Logout.scss +++ /dev/null @@ -1,11 +0,0 @@ -@use '@redhat-cloud-services/frontend-components-utilities/styles/mixins' as *; - -.land-c-page__logout { - display: flex; - justify-content: center; - flex-direction: column; - text-align: center; - - h1 { @include rem('margin-bottom', 30px); } - button { @include rem('font-size', 20px); } -} \ No newline at end of file diff --git a/src/routes/Logout.stories.tsx b/src/routes/Logout.stories.tsx deleted file mode 100644 index 1bbbc892..00000000 --- a/src/routes/Logout.stories.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react-vite'; -import { expect, within } from 'storybook/test'; - -import Logout from './Logout'; - -const meta: Meta = { - title: 'Routes/Logout', - component: Logout, -}; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - play: async ({ canvasElement }) => { - const canvas = within(canvasElement); - await expect( - canvas.getByRole('heading', { name: 'You have logged out.' }), - ).toBeInTheDocument(); - await expect( - canvas.getByRole('button', { name: 'Take me home' }), - ).toBeInTheDocument(); - }, -}; diff --git a/src/routes/Logout.tsx b/src/routes/Logout.tsx deleted file mode 100644 index 202aaf20..00000000 --- a/src/routes/Logout.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { Button } from '@patternfly/react-core/dist/dynamic/components/Button'; -import { Title } from '@patternfly/react-core/dist/dynamic/components/Title'; -import React from 'react'; - -import './Logout.scss'; - -const onButtonClick = (url: string) => { - window.location.href = `./${url}`; -}; - -const Logout = () => ( -
- - You have logged out. - - -
-); - -export default Logout; diff --git a/src/routes/Maintenance.scss b/src/routes/Maintenance.scss deleted file mode 100644 index 794b663a..00000000 --- a/src/routes/Maintenance.scss +++ /dev/null @@ -1,12 +0,0 @@ -.land-c-page__maintenance { - display: flex; - justify-content: center; - text-align: center; - - .pf-v6-c-empty-state { margin-top: 64px; } - - svg { - margin-bottom: var(--pf-v6-c-empty-state__icon--MarginBottom); - height: 100px; - } -} \ No newline at end of file diff --git a/src/routes/Maintenance.stories.tsx b/src/routes/Maintenance.stories.tsx deleted file mode 100644 index c94e8408..00000000 --- a/src/routes/Maintenance.stories.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react-vite'; -import { expect, within } from 'storybook/test'; - -import Maintenance from './Maintenance'; - -const meta: Meta = { - title: 'Routes/Maintenance', - component: Maintenance, -}; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - play: async ({ canvasElement }) => { - const canvas = within(canvasElement); - await expect( - canvas.getByText('Maintenance in progress'), - ).toBeInTheDocument(); - await expect( - canvas.getByText( - /console\.redhat\.com is currently undergoing scheduled maintenance/, - ), - ).toBeInTheDocument(); - await expect( - canvas.getByText('We will be back soon. Thank you for your patience!'), - ).toBeInTheDocument(); - const statusLink = canvas.getByRole('link', { - name: /status\.redhat\.com/, - }); - await expect(statusLink).toHaveAttribute( - 'href', - 'http://status.redhat.com/incidents/qw4mmmyzwzdg', - ); - await expect( - canvas.getByRole('link', { name: 'Return to homepage' }), - ).toBeInTheDocument(); - }, -}; diff --git a/src/routes/Maintenance.tsx b/src/routes/Maintenance.tsx deleted file mode 100644 index 89a26c3a..00000000 --- a/src/routes/Maintenance.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { Button } from '@patternfly/react-core/dist/dynamic/components/Button'; -import { - EmptyState, - EmptyStateBody, - EmptyStateFooter, - EmptyStateVariant, -} from '@patternfly/react-core/dist/dynamic/components/EmptyState'; -import React from 'react'; -import IconHourglass from '../components/icon-hourglass'; -import './Maintenance.scss'; - -const isBeta = () => { - return window.location.pathname.split('/')[1] === 'beta' ? '/beta' : ''; -}; - -const Maintenance = () => ( -
- - -

- console.redhat.com is currently undergoing scheduled maintenance and - will be unavailable from 16:00 - 22:00 UTC (12:00 PM - 6:00 PM EST). -

-

- For more information visit  - - status.redhat.com. - -

-

We will be back soon. Thank you for your patience!

-
- - - -
-
-); - -export default Maintenance; diff --git a/src/routes/__tests__/404.test.tsx b/src/routes/__tests__/404.test.tsx deleted file mode 100644 index 5e5592ef..00000000 --- a/src/routes/__tests__/404.test.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import NotFound from '../404'; - -describe('404 page', () => { - it('should render correctly', () => { - const { container } = render(); - expect(container).toMatchSnapshot(); - }); - - it('click: Return to homepage', () => { - render(); - screen.getByText('Return to homepage').click(); - expect(window.location.pathname).toBe('/'); - }); -}); diff --git a/src/routes/__tests__/Logout.test.tsx b/src/routes/__tests__/Logout.test.tsx deleted file mode 100644 index 13ed0d6a..00000000 --- a/src/routes/__tests__/Logout.test.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import Logout from '../Logout'; -import { render, screen } from '@testing-library/react'; - -describe('Logout component', () => { - it('should render correctly', () => { - const { container } = render(); - expect(container).toMatchSnapshot(); - }); - - it('click: take me home', () => { - render(); - screen.getByText('Take me home').click(); - expect(window.location.pathname).toBe('/'); - }); -}); diff --git a/src/routes/__tests__/Maintenance.test.tsx b/src/routes/__tests__/Maintenance.test.tsx deleted file mode 100644 index af1b180b..00000000 --- a/src/routes/__tests__/Maintenance.test.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import Maintenance from '../Maintenance'; - -describe('Maintenance page', () => { - it('should render correctly', () => { - const { container } = render(); - expect(container).toMatchSnapshot(); - }); - - it('Maintenance: go home', () => { - render(); - screen.getByText('Return to homepage').click(); - expect(window.location.pathname).toBe('/'); - }); -}); diff --git a/src/routes/__tests__/__snapshots__/404.test.tsx.snap b/src/routes/__tests__/__snapshots__/404.test.tsx.snap deleted file mode 100644 index 9babbdd2..00000000 --- a/src/routes/__tests__/__snapshots__/404.test.tsx.snap +++ /dev/null @@ -1,281 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`404 page > should render correctly 1`] = ` -
-
-
-

- 404: We lost that page -

- - - - - - - - - - - - 404path-not-found - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- Let's find you a new one. Try a new search or return home. -

- - - Return to homepage - - -
-
-
-`; diff --git a/src/routes/__tests__/__snapshots__/Logout.test.tsx.snap b/src/routes/__tests__/__snapshots__/Logout.test.tsx.snap deleted file mode 100644 index 52bcb2b6..00000000 --- a/src/routes/__tests__/__snapshots__/Logout.test.tsx.snap +++ /dev/null @@ -1,31 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`Logout component > should render correctly 1`] = ` -
-
-

- You have logged out. -

- -
-
-`; diff --git a/src/routes/__tests__/__snapshots__/Maintenance.test.tsx.snap b/src/routes/__tests__/__snapshots__/Maintenance.test.tsx.snap deleted file mode 100644 index c687f80a..00000000 --- a/src/routes/__tests__/__snapshots__/Maintenance.test.tsx.snap +++ /dev/null @@ -1,226 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`Maintenance page > should render correctly 1`] = ` -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-

- Maintenance in progress -

-
-
-
-

- console.redhat.com is currently undergoing scheduled maintenance and will be unavailable from 16:00 - 22:00 UTC (12:00 PM - 6:00 PM EST). -

-

- For more information visit  - - status.redhat.com. - -

-

- We will be back soon. Thank you for your patience! -

-
- -
-
-
-
-`; diff --git a/vitest.config.ts b/vitest.config.ts index da623327..d4f3a174 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -13,12 +13,6 @@ export default defineConfig({ // its transform from the react-vite framework itself). jsx: 'automatic', }, - resolve: { - alias: { - // Handle .js extensions in imports (ESM) - '^(\\.{1,2}/.*)\\.js$': '$1', - }, - }, css: { modules: { localsConvention: 'camelCase',