Skip to content

Commit

Permalink
feat(pci-cold-archive): initialize react app
Browse files Browse the repository at this point in the history
ref: DTCORE-3019
Signed-off-by: Yoann Fievez <[email protected]>
  • Loading branch information
kqesar committed Jan 31, 2025
1 parent 128a3ba commit d985442
Show file tree
Hide file tree
Showing 26 changed files with 622 additions and 3 deletions.
1 change: 1 addition & 0 deletions packages/manager/apps/pci-cold-archive/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# PCI Cold Archive
12 changes: 12 additions & 0 deletions packages/manager/apps/pci-cold-archive/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>OVHcloud</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="./src/main.tsx"></script>
</body>
</html>
70 changes: 70 additions & 0 deletions packages/manager/apps/pci-cold-archive/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"name": "@ovh-ux/manager-pci-cold-archive-app",
"version": "0.0.0",
"private": true,
"description": "PCI Cold Archive react app",
"type": "module",
"scripts": {
"build": "tsc --project tsconfig.build.json && vite build",
"coverage": "vitest run --coverage",
"dev": "vite",
"lint": "eslint ./src",
"start": "lerna exec --stream --scope='@ovh-ux/manager-pci-cold-archive-app' --include-dependencies -- npm run build --if-present",
"start:dev": "lerna exec --stream --scope='@ovh-ux/manager-pci-cold-archive-app' --include-dependencies -- npm run dev --if-present",
"start:watch": "lerna exec --stream --parallel --scope='@ovh-ux/manager-pci-cold-archive-app' --include-dependencies -- npm run dev:watch --if-present",
"test": "vitest run"
},
"dependencies": {
"@ovh-ux/manager-config": "^8.0.2",
"@ovh-ux/manager-core-api": "^0.9.0",
"@ovh-ux/manager-pci-common": "^1.0.6",
"@ovh-ux/manager-react-components": "^2.6.2",
"@ovh-ux/manager-react-core-application": "^0.11.5",
"@ovh-ux/manager-react-shell-client": "^0.8.5",
"@ovh-ux/manager-tailwind-config": "^0.2.1",
"@ovh-ux/shell": "^4.1.2",
"@ovhcloud/ods-components": "18.5.0",
"@ovhcloud/ods-themes": "18.5.0",
"@tanstack/react-query": "^5.51.21",
"@tanstack/react-table": "^8.20.1",
"element-internals-polyfill": "^1.3.12",
"i18next": "^23.8.2",
"i18next-http-backend": "^2.5.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.52.1",
"react-i18next": "^14.0.5",
"react-router-dom": "^6.24.1",
"react-use": "^17.5.0",
"zustand": "^4.5.5"
},
"devDependencies": {
"@jest/globals": "^29.7.0",
"@ovh-ux/manager-vite-config": "^0.9.0",
"@tanstack/react-query-devtools": "^5.50.1",
"@testing-library/dom": "^10.1.0",
"@testing-library/jest-dom": "^6.4.5",
"@testing-library/react": "^16.0.0",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.12",
"@types/react": "^18.2.79",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.0",
"@vitest/coverage-v8": "^1.6.0",
"autoprefixer": "^10.4.19",
"eslint": "^8.57.0",
"postcss": "^8.4.38",
"rollup": "^4.18.0",
"tailwindcss": "^3.4.4",
"typescript": "^5.4.5",
"vite": "^5.3.3",
"vitest": "^1.6.0"
},
"regions": [
"CA",
"EU"
],
"universes": [
"@ovh-ux/manager-public-cloud"
]
}
6 changes: 6 additions & 0 deletions packages/manager/apps/pci-cold-archive/postcss.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
20 changes: 20 additions & 0 deletions packages/manager/apps/pci-cold-archive/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { HashRouter } from 'react-router-dom';
import RoutesComponent from '@/routes';
import queryClient from './queryClient';

import '@ovhcloud/ods-themes/default';

function App() {
return (
<QueryClientProvider client={queryClient}>
<HashRouter>
<RoutesComponent />
</HashRouter>
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
}

export default App;
12 changes: 12 additions & 0 deletions packages/manager/apps/pci-cold-archive/src/core/HidePreloader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ShellContext } from '@ovh-ux/manager-react-shell-client';
import { useContext, useEffect } from 'react';

export default function HidePreloader() {
const { ux } = useContext(ShellContext).shell;

useEffect(() => {
ux.hidePreloader();
}, []);

return null;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ShellContext } from '@ovh-ux/manager-react-shell-client';
import { useContext, useEffect } from 'react';
import { useLocation } from 'react-router-dom';

export default function ShellRoutingSync() {
const location = useLocation();

const { routing } = useContext(ShellContext).shell;
useEffect(() => {
routing.stopListenForHashChange();
}, []);
useEffect(() => {
routing.onHashChange();
}, [location]);
return null;
}
39 changes: 39 additions & 0 deletions packages/manager/apps/pci-cold-archive/src/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { PaginationState } from '@ovh-ux/manager-react-components';
import { ColumnSort } from '@tanstack/react-table';

export const paginateResults = <T>(
items: T[],
pagination: PaginationState,
) => ({
rows: items.slice(
pagination.pageIndex * pagination.pageSize,
(pagination.pageIndex + 1) * pagination.pageSize,
),
pageCount: Math.ceil(items.length / pagination.pageSize),
totalRows: items.length,
});

export const compareFunction = <T>(key: keyof T) => (a: T, b: T) => {
const aValue = a[key] || '';
const bValue = b[key] || '';

if (typeof aValue === 'number' && typeof bValue === 'number') {
return aValue - bValue;
}
return aValue.toString().localeCompare(bValue.toString());
};

export const sortResults = <T>(items: T[], sorting: ColumnSort): T[] => {
const data = [...items];

if (sorting) {
const { id: sortKey, desc } = sorting;
data.sort(compareFunction<T>(sortKey as keyof T));

if (desc) {
data.reverse();
}
}

return data;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useContext, useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import { ShellContext } from '@ovh-ux/manager-react-shell-client';
import { useProject } from '@ovh-ux/manager-pci-common';
import { PAGE_PREFIX, PCI_LEVEL2 } from '@/tracking.constants';

const DISCOVERY_PLANCODE = 'project.discovery';

export default function usePageTracking() {
const location = useLocation();
const { data: project } = useProject();
const { setPciProjectMode, trackPage } = useContext(
ShellContext,
).shell.tracking;

useEffect(() => {
if (project) {
setPciProjectMode({
projectId: project.project_id,
isDiscoveryProject: project.planCode === DISCOVERY_PLANCODE,
});
}
}, [project]);

useEffect(() => {
const pageId = location.pathname.split('/').pop();
const pageKey = pageId === 'coldArchive' ? '' : `::${pageId}`;
trackPage({
name: `${PAGE_PREFIX}::${pageKey}`,
level2: PCI_LEVEL2,
});
}, [location]);
}
7 changes: 7 additions & 0 deletions packages/manager/apps/pci-cold-archive/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

.application {
@apply md:mx-12 mt-8;
}
43 changes: 43 additions & 0 deletions packages/manager/apps/pci-cold-archive/src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import {
initI18n,
initShellContext,
ShellContext,
} from '@ovh-ux/manager-react-shell-client';
import App from './App';

import './index.css';

import '@/vite-hmr.ts';

const init = async (
appName: string,
{ reloadOnLocaleChange } = { reloadOnLocaleChange: false },
) => {
const context = await initShellContext(appName);

const region = context.environment.getRegion();
try {
await import(`./config-${region}.js`);
} catch (error) {
// nothing to do
}

await initI18n({
context,
reloadOnLocaleChange,
ns: ['common'],
defaultNS: 'common',
});

ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<ShellContext.Provider value={context}>
<App />
</ShellContext.Provider>
</React.StrictMode>,
);
};

init('pci-cold-archive');
55 changes: 55 additions & 0 deletions packages/manager/apps/pci-cold-archive/src/pages/Layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Outlet, useRouteError } from 'react-router-dom';

import { ShellContext } from '@ovh-ux/manager-react-shell-client';
import { Suspense, useContext } from 'react';
import { ErrorBanner } from '@ovh-ux/manager-react-components';
import { ApiError } from '@ovh-ux/manager-core-api';
import { useProject } from '@ovh-ux/manager-pci-common';
import ShellRoutingSync from '@/core/ShellRoutingSync';
import HidePreloader from '@/core/HidePreloader';

import usePageTracking from '@/hooks/usePageTracking';

export default function Layout() {
const { isSuccess } = useProject();
usePageTracking();
return (
<div className="application">
<Suspense>
<ShellRoutingSync />
{isSuccess && (
<>
<HidePreloader />
<Outlet />
</>
)}
</Suspense>
</div>
);
}

export const ErrorBoundary = () => {
const error = useRouteError() as ApiError;
const nav = useContext(ShellContext).shell.navigation;

const redirectionApplication = 'public-cloud';

const navigateToHomePage = () => {
nav.navigateTo(redirectionApplication, '', {});
};

const reloadPage = () => {
nav.reload();
};
return (
<Suspense>
<ErrorBanner
onReloadPage={reloadPage}
onRedirectHome={navigateToHomePage}
error={error.response}
/>
<ShellRoutingSync />
<HidePreloader />
</Suspense>
);
};
11 changes: 11 additions & 0 deletions packages/manager/apps/pci-cold-archive/src/queryClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { QueryClient } from '@tanstack/react-query';

export const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 300_000,
},
},
});

export default queryClient;
18 changes: 18 additions & 0 deletions packages/manager/apps/pci-cold-archive/src/routes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { lazy } from 'react';
import { Route, Routes } from 'react-router-dom';

const ROUTE_PATHS = {
ROOT: '/pci/projects/:projectId/storages/cold-archive',
LISTING: '',
};

const LayoutPage = lazy(() => import('@/pages/Layout'));

const RoutesComponent = () => (
<Routes>
<Route id="root" path={ROUTE_PATHS.ROOT} Component={LayoutPage}></Route>
<Route path="" element={<>Page not found</>}></Route>
</Routes>
);

export default RoutesComponent;
5 changes: 5 additions & 0 deletions packages/manager/apps/pci-cold-archive/src/sampleTest.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
describe('Sample Test', () => {
it('should test that true === true', () => {
expect(true).toBe(true);
});
});
Loading

0 comments on commit d985442

Please sign in to comment.