Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(*): init logs to customer module #14281

Open
wants to merge 2 commits into
base: feat/logs-to-customer-module
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"test:coverage": "vitest run --coverage"
},
"dependencies": {
"@ovh-ux/logs-to-customer": "^1.0.0",
"@ovh-ux/manager-config": "^8.0.0",
"@ovh-ux/manager-core-api": "^0.9.0",
"@ovh-ux/manager-core-utils": "*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"general_informations": "Informations générales",
"encrypted_keys": "Clés de chiffrement",
"access_certificates": "Certificats d'accès",
"logs": "Logs",
"key_management_service_dashboard_back_link": "Retour à la liste des KMS",
"key_management_service_dashboard_tab_comming_soon": "prochainement",
"key_management_service_dashboard_field_label_name": "Nom du KMS",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"key_management_service_logs": "logs",
"key_management_service_logs_description": "Une description à définir."
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ const Dashboard: React.FC<DashboardLayoutProps> = ({ tabs }) => {

useEffect(() => {
const activeTab = tabs.find(
(tab) => `/${okmsId}/${tab.url}` === location.pathname,
(tab) =>
tab.url !== '' && location.pathname.startsWith(`/${okmsId}/${tab.url}`),
);

if (!activeTab) return;
setActivePanel(activeTab?.url);
}, [location]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ export default function DashboardPage() {
const { t: tCredentials } = useTranslation(
'key-management-service/credential',
);
const { t: tLogs } = useTranslation('key-management-service/logs');

const { okmsId } = useParams();
const {
data: okms,
Expand Down Expand Up @@ -82,6 +84,10 @@ export default function DashboardPage() {
url: ROUTES_URLS.credentials,
title: tDashboard('access_certificates'),
},
{
url: ROUTES_URLS.logs,
title: tDashboard('logs'),
},
];

const breadcrumbItems: BreadcrumbItem[] = [
Expand All @@ -105,6 +111,11 @@ export default function DashboardPage() {
label: tDashboard('key_management_service_update_name'),
navigateTo: `/${okmsId}/${ROUTES_URLS.okmsUpdateName}`,
},
{
id: ROUTES_URLS.logs,
label: tLogs('key_management_service_logs'),
navigateTo: `/${okmsId}/${ROUTES_URLS.logs}`,
},
];

const headerProps: HeadersProps = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import LogsToCustomerModule from '@ovh-ux/logs-to-customer/src/LogsToCustomer.module';
import { Description } from '@ovh-ux/manager-react-components';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { useParams } from 'react-router-dom';

export default function KmsLogs() {
const { okmsId } = useParams();
const { t } = useTranslation('key-management-service/logs');

return (
<div className="flex flex-col gap-4">
<Description>{t('key_management_service_logs_description')}</Description>
<LogsToCustomerModule
logApiVersion="v2"
logApiBaseUrl={`/okms/resource/${okmsId}/log`}
/>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const ROUTES_URLS = {
okmsUpdateName: 'update-name',
keys: 'keys',
keyId: ':keyId',
logs: 'logs',
createKmsServiceKey: 'create',
serviceKeyEditName: 'edit-name',
serviceKeyDeactivate: 'deactivate',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import logsRoutes from '@ovh-ux/logs-to-customer/src/routes/routes';
import { PageType } from '@ovh-ux/manager-react-shell-client';
import NotFound from '../pages/404';
import { ROUTES_URLS } from './routes.constants';
Expand Down Expand Up @@ -157,6 +158,13 @@ export default [
},
],
},
{
path: `${ROUTES_URLS.logs}/*`,
...lazyRouteConfig(() =>
import('@/pages/dashboard/logs/Logs.page'),
),
children: [...logsRoutes],
},
],
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ module.exports = {
...config,
content: [
'./src/**/*.{js,jsx,ts,tsx}',
path.join(
path.dirname(require.resolve('@ovh-ux/logs-to-customer')),
'**/*.{js,jsx,ts,tsx}',
),
path.join(
path.dirname(require.resolve('@ovh-ux/manager-react-components')),
'**/*.{js,jsx,ts,tsx}',
Expand Down
43 changes: 43 additions & 0 deletions packages/manager/modules/logs-to-customer/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"name": "@ovh-ux/logs-to-customer",
"version": "1.0.0",
"private": true,
"description": "",
"license": "BSD-3-Clause",
"author": "OVH SAS",
"type": "module",
"main": "./src/index.ts",
"scripts": {
"dev": "tsc"
},
"dependencies": {},
"devDependencies": {
"@ovh-ux/manager-core-api": "^0.9.0",
"@ovh-ux/manager-react-components": "^1.41.1",
"@ovh-ux/manager-vite-config": "^0.8.2",
"@testing-library/react": "^16.0.0",
"@vitejs/plugin-react": "^4.2.1",
"react-i18next": "^14.0.5",
"tailwindcss": "^3.4.4",
"typescript": "^4.3.2",
"vite": "^5.2.13",
"vitest": "^1.2.0"
},
"peerDependencies": {
"@ovh-ux/manager-core-api": "^0.9.0",
"@ovh-ux/manager-react-components": "^1.41.1",
"@ovh-ux/manager-react-shell-client": "^0.8.1",
"@ovh-ux/manager-tailwind-config": "^0.2.0",
"@ovhcloud/ods-common-core": "17.2.2",
"@ovhcloud/ods-common-theming": "17.2.2",
"@ovhcloud/ods-components": "17.2.2",
"@ovhcloud/ods-theme-blue-jeans": "17.2.2",
"@tanstack/react-query": "^5.51.21",
"i18next": "^23.8.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^14.0.5",
"react-router": "^6.21.3",
"react-router-dom": "^6.3.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { createContext } from 'react';
import { LogKind } from './data/types/dbaas/logs';

export interface LogProviderProps {
currentLogKind?: LogKind;
logApiBaseUrl: string;
}

export const LogsContext = createContext<LogProviderProps>({
logApiBaseUrl: '',
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import React, { useEffect, useMemo, useState } from 'react';
import { Outlet } from 'react-router-dom';
import { useQueryClient } from '@tanstack/react-query';
import {
OsdsButton,
OsdsMessage,
OsdsSpinner,
OsdsText,
} from '@ovhcloud/ods-components/react';
import {
ODS_BUTTON_SIZE,
ODS_BUTTON_VARIANT,
ODS_MESSAGE_TYPE,
ODS_SPINNER_SIZE,
} from '@ovhcloud/ods-components';
import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming';
import { getLogKindsQueryKey, useLogKinds } from './data/hooks/useLogKinds';
import LogKindsSelector from './components/logKindsSelector/LogKindsSelector.component';
import { LogKind } from './data/types/dbaas/logs';
import { LogApiVersion } from './data/types/apiVersion';
import { LogsContext } from './LogsToCustomer.context';

export interface ILogsToCustomerModule {
logApiBaseUrl: string;
logApiVersion: LogApiVersion;
}

export default function LogsToCustomerModule({
logApiBaseUrl,
logApiVersion,
}: Readonly<ILogsToCustomerModule>) {
const queryClient = useQueryClient();
const [currentLogKind, setCurrentLogKind] = useState<LogKind>();

const { data: logKinds, error, isPending } = useLogKinds({
baseUrl: logApiBaseUrl,
apiVersion: logApiVersion,
});

useEffect(() => {
if (!isPending && logKinds?.length > 0) setCurrentLogKind(logKinds[0]);
}, [logKinds, isPending]);

const LogsContextValues = useMemo(
() => ({
currentLogKind,
logApiBaseUrl,
}),
[currentLogKind, logApiBaseUrl],
);

if (isPending)
return (
<div className="flex py-8">
<OsdsSpinner inline size={ODS_SPINNER_SIZE.md} />
</div>
);

if (error)
return (
<div className="flex flex-col gap-4">
<OsdsMessage
color={ODS_THEME_COLOR_INTENT.error}
type={ODS_MESSAGE_TYPE.error}
>
<OsdsText color={ODS_THEME_COLOR_INTENT.error}>
<div>Une erreur est survenue</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

manage translation

{error && <strong>{error.message}</strong>}
</OsdsText>
</OsdsMessage>
<OsdsButton
size={ODS_BUTTON_SIZE.sm}
color={ODS_THEME_COLOR_INTENT.primary}
variant={ODS_BUTTON_VARIANT.flat}
onClick={() =>
queryClient.refetchQueries({
queryKey: getLogKindsQueryKey(logApiBaseUrl),
})
}
>
reload logs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

manage translation

</OsdsButton>
</div>
);

if (logKinds.length === 0) return <div>no logkinds</div>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

manage translation


return (
<div className="flex flex-col gap-8">
<LogKindsSelector
logKinds={logKinds}
currentLogKind={currentLogKind}
setCurrentLogKind={setCurrentLogKind}
/>
<LogsContext.Provider value={LogsContextValues}>
<Outlet />
</LogsContext.Provider>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Description } from '@ovh-ux/manager-react-components';
import { OsdsSelect, OsdsSelectOption } from '@ovhcloud/ods-components/react';
import './translations';
import { LogKind } from '../../data/types/dbaas/logs';

interface ILogKindsSelector {
logKinds: LogKind[];
currentLogKind: LogKind;
setCurrentLogKind: React.Dispatch<React.SetStateAction<LogKind>>;
}

export default function LogKindsSelector({
logKinds,
currentLogKind,
setCurrentLogKind,
}: Readonly<ILogKindsSelector>) {
const { t } = useTranslation('logKindsSelector');

// TODO: Design Specs for usecase: One kind.
if (logKinds.length === 1) {
return <div>{logKinds[0].displayName}</div>;
}

return (
<div className="flex flex-col gap-4">
<Description>{t('logKindsSelector_select_label')}</Description>
<OsdsSelect
value={currentLogKind?.kindId}
onOdsValueChange={(event) => {
const newLogKind = logKinds.find(
(k) => k.kindId === event.detail.value,
);
setCurrentLogKind(newLogKind);
Comment on lines +32 to +35
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if newLogKind is undefined (not found), is it OK to reset the currentLogKind ?

}}
>
{logKinds.map((k) => (
<OsdsSelectOption key={k.kindId} value={k.kindId}>
{k.displayName}
</OsdsSelectOption>
))}
</OsdsSelect>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"logKindsSelector_select_label": "Sélectionnez le type de log"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import i18next from 'i18next';

// import de_DE from './Messages_de_DE.json';
// import en_GB from './Messages_en_GB.json';
Comment on lines +3 to +4
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be managed with fast translation to avoid commenting all the translation imports

// import es_ES from './Messages_es_ES.json';
// import fr_CA from './Messages_fr_CA.json';
import fr_FR from './Messages_fr_FR.json';
// import it_IT from './Messages_it_IT.json';
// import pl_PL from './Messages_pl_PL.json';
// import pt_PT from './Messages_pt_PT.json';

function addTranslations() {
// i18next.addResources('de_DE', 'logKindsSelector', de_DE);
// i18next.addResources('en_GB', 'logKindsSelector', en_GB);
// i18next.addResources('es_ES', 'logKindsSelector', es_ES);
// i18next.addResources('fr_CA', 'logKindsSelector', fr_CA);
i18next.addResources('fr_FR', 'logKindsSelector', fr_FR);
// i18next.addResources('it_IT', 'logKindsSelector', it_IT);
// i18next.addResources('pl_PL', 'logKindsSelector', pl_PL);
// i18next.addResources('pt_PT', 'logKindsSelector', pt_PT);
}

if (i18next.isInitialized) {
addTranslations();
} else {
i18next.on('initialized', addTranslations);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React, { useContext } from 'react';
import { LogsContext } from '../../LogsToCustomer.context';

export default function LogsTail() {
const { currentLogKind, logApiBaseUrl } = useContext(LogsContext);

return (
<div className="flex gap-8 flex-col p-8">
<h3>Live tail</h3>
<ul>
<li>
CurrentLogKind: <b>{currentLogKind?.displayName}</b>
</li>
<li>
logApiBaseUrl: <b>{logApiBaseUrl}</b>
</li>
</ul>
Comment on lines +9 to +17
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No translation needed ? At least it should be readable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is temporary content, everything in theses components will be reworked.

</div>
);
}
Loading
Loading