* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { Card, CenteredLayout, Link, PageContentFontWrapper, Title } from 'design-system';
import * as React from 'react';
import { Helmet } from 'react-helmet-async';
-import Link from '../../components/common/Link';
import { translate } from '../../helpers/l10n';
-import SimpleContainer from './SimpleContainer';
-interface Props {
- withContainer?: boolean;
-}
-
-export default function NotFound({ withContainer = true }: Props) {
- const Container = withContainer ? SimpleContainer : React.Fragment;
+export default function NotFound() {
return (
- <Container>
+ <>
<Helmet defaultTitle={translate('404_not_found')} defer={false} />
- <div className="page-wrapper-simple" id="bd">
- <div className="page-simple" id="nonav">
- <h2 className="big-spacer-bottom">{translate('page_not_found')}</h2>
- <p className="spacer-bottom">{translate('address_mistyped_or_page_moved')}</p>
- <p>
- <Link to="/">{translate('go_back_to_homepage')}</Link>
- </p>
- </div>
- </div>
- </Container>
+ <PageContentFontWrapper className="sw-body-md">
+ <CenteredLayout className="sw-flex sw-flex-col sw-items-center">
+ <Card className="sw-m-14 sw-w-abs-600">
+ <Title>{translate('page_not_found')}</Title>
+ <p className="sw-mb-2">{translate('address_mistyped_or_page_moved')}</p>
+ <p>
+ <Link to="/">{translate('go_back_to_homepage')}</Link>
+ </p>
+ </Card>
+ </CenteredLayout>
+ </PageContentFontWrapper>
+ </>
);
}
const { pluginKey, extensionKey } = useParams();
const { adminPages } = useOutletContext<AdminPagesContext>();
- const extension = (adminPages || []).find((p) => p.key === `${pluginKey}/${extensionKey}`);
- return extension ? <Extension extension={extension} /> : <NotFound withContainer={false} />;
+ const extension = adminPages?.find((p) => p.key === `${pluginKey}/${extensionKey}`);
+ return extension ? <Extension extension={extension} /> : <NotFound />;
}
import * as React from 'react';
import { useParams } from 'react-router-dom';
import { AppState } from '../../../types/appstate';
-import withAppStateContext from '../app-state/withAppStateContext';
import NotFound from '../NotFound';
+import withAppStateContext from '../app-state/withAppStateContext';
import Extension from './Extension';
export interface GlobalPageExtensionProps {
? `${params.pluginKey}/${params.extensionKey}`
: `${pluginKey}/${extensionKey}`;
- const extension = (globalPages || []).find((p) => p.key === fullKey);
- return extension ? <Extension extension={extension} /> : <NotFound withContainer={false} />;
+ const extension = globalPages?.find((p) => p.key === fullKey);
+ return extension ? <Extension extension={extension} /> : <NotFound />;
}
export default withAppStateContext(GlobalPageExtension);
// We keep that for compatibility but ideally should advocate to use tanstack query
const onBranchesChange = useRefreshBranches();
- const extension =
- component &&
- component.configuration &&
- (component.configuration.extensions || []).find(
- (p) => p.key === `${pluginKey}/${extensionKey}`,
- );
+ const extension = component?.configuration?.extensions?.find(
+ (p) => p.key === `${pluginKey}/${extensionKey}`,
+ );
return extension ? (
<Extension extension={extension} options={{ component, onComponentChange, onBranchesChange }} />
) : (
- <NotFound withContainer={false} />
+ <NotFound />
);
}
? `${params.pluginKey}/${params.extensionKey}`
: `${pluginKey}/${extensionKey}`;
- const extension = component.extensions && component.extensions.find((p) => p.key === fullKey);
+ const extension = component.extensions?.find((p) => p.key === fullKey);
return extension ? (
<Extension extension={extension} options={{ branchLike, component }} />
) : (
- <NotFound withContainer={false} />
+ <NotFound />
);
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import { screen } from '@testing-library/react';
+import * as React from 'react';
+import { Outlet, Route } from 'react-router-dom';
+import { renderAppRoutes } from '../../../../helpers/testReactTestingUtils';
+import { AdminPagesContext } from '../../../../types/admin';
+import { Extension } from '../../../../types/types';
+import GlobalAdminPageExtension from '../GlobalAdminPageExtension';
+
+jest.mock('../Extension', () => ({
+ __esModule: true,
+ default(props: { extension: { key: string; name: string } }) {
+ return <h1>{props.extension.name}</h1>;
+ },
+}));
+
+const extensions = [{ key: 'plugin123/ext42', name: 'extension 42' }];
+
+it('should find the extension from params', () => {
+ renderGlobalAdminPageExtension('admin/extension/plugin123/ext42', extensions);
+
+ expect(screen.getByText('extension 42')).toBeInTheDocument();
+});
+
+it('should notify if extension is not found', () => {
+ renderGlobalAdminPageExtension('admin/extension/plugin123/wrong-extension', extensions);
+
+ expect(screen.getByText('page_not_found')).toBeInTheDocument();
+});
+
+function renderGlobalAdminPageExtension(navigateTo: string, adminPages: Extension[] = []) {
+ renderAppRoutes(
+ `admin/extension/:pluginKey/:extensionKey`,
+ () => (
+ <Route path="admin" element={<Wrapper adminPages={adminPages} />}>
+ <Route path="extension/:pluginKey/:extensionKey" element={<GlobalAdminPageExtension />} />
+ </Route>
+ ),
+ {
+ navigateTo,
+ },
+ );
+}
+
+function Wrapper(props: Readonly<AdminPagesContext>) {
+ return <Outlet context={props} />;
+}
path="admin/plugin_risk_consent"
element={<PluginRiskConsent />}
/>
- <Route path="not_found" element={<NotFound />} />
- <Route path="*" element={<NotFound />} />
+
+ <Route element={<SimpleContainer />}>
+ <Route path="not_found" element={<NotFound />} />
+ <Route path="*" element={<NotFound />} />
+ </Route>
</Route>
</Route>
</>,