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(mrc): add changelog component to mrc v1.x #14895

Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ export interface HeadersProps {
subtitle?: string;
description?: string;
headerButton?: React.ReactElement;
changelogButton?: React.ReactElement;
}

export const Headers: React.FC<HeadersProps> = ({
title,
subtitle,
description,
headerButton,
changelogButton,
}) => {
return (
<div className="flex items-center justify-between">
Expand All @@ -23,7 +25,12 @@ export const Headers: React.FC<HeadersProps> = ({
<Description className="mb-6">{description}</Description>
)}
</div>
{headerButton && <div>{headerButton}</div>}
{(headerButton || changelogButton) && (
<div className="flex flex-wrap justify-end">
{changelogButton}
{headerButton}
</div>
)}
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import { vitest } from 'vitest';
import { vitest, vi } from 'vitest';
import { waitFor, screen } from '@testing-library/react';
import { render } from '../../../utils/test.provider';
import {
header,
subHeader,
headerWithGuides,
headerWithHeaderButtons,
headerWithActions,
} from './headers.stories';
import { IamAuthorizationResponse } from '../../../hooks/iam/iam.interface';
import { useAuthorizationIam } from '../../../hooks/iam';

vitest.mock('../../../hooks/iam');
vitest.mock('@ovh-ux/manager-react-shell-client', () => ({
useOvhTracking: () => ({
trackClick: vi.fn(),
}),
}));

const mockedHook =
useAuthorizationIam as unknown as jest.Mock<IamAuthorizationResponse>;
Expand Down Expand Up @@ -40,11 +45,13 @@ describe('Headers component', () => {
});
});

it('renders header with guides correctly', async () => {
render(headerWithGuides());
it('renders header with header buttons correctly', async () => {
render(headerWithHeaderButtons());
await waitFor(() => {
expect(
screen.getByText('Example for header with guides'),
screen.getByText(
'Example for header with header button and changelog button',
),
).toBeInTheDocument();
expect(screen.getByText('description for subheader')).toBeInTheDocument();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { OdsHTMLAnchorElementTarget } from '@ovhcloud/ods-common-core';
import Headers, { HeadersProps } from './headers.component';
import ActionMenu from '../../navigation/menus/action/action.component';
import GuideButton from '../../navigation/menus/guide/guide.component';
import ChangelogButton, {
ChangelogLinks,
} from '../../navigation/menus/changelog/changelog.component';

const Heading: HeadersProps = {
title: 'Example for header',
Expand Down Expand Up @@ -44,20 +47,35 @@ const guideItems = [
},
];

const changelogChapters: string[] = ['baremetal', 'server', 'dedicated'];
const changelogLinks: ChangelogLinks = {
roadmap:
'https://github.com/orgs/ovh/projects/16/views/1?pane=info&sliceBy%5Bvalue%5D=Baremetal',
changelog:
'https://github.com/orgs/ovh/projects/16/views/1?pane=info&sliceBy%5Bvalue%5D=Baremetal',
'feature-request':
'https://github.com/orgs/ovh/projects/16/views/1?pane=info&sliceBy%5Bvalue%5D=Baremetal',
};

const HeadingWithActionButton: HeadersProps = {
title: 'Example for header with actions ',
description: 'description for header',
headerButton: <ActionMenu items={actionItems} />,
};
const HeadingWithGuideButton: HeadersProps = {
title: 'Example for header with guides',
const HeadingWithHeaderButtons: HeadersProps = {
title: 'Example for header with header button and changelog button',
description: 'description for subheader',
headerButton: <GuideButton items={guideItems} />,
changelogButton: (
<ChangelogButton links={changelogLinks} chapters={changelogChapters} />
),
};

export const header = () => <Headers {...Heading} />;
export const subHeader = () => <Headers {...SubHeading} />;
export const headerWithGuides = () => <Headers {...HeadingWithGuideButton} />;
export const headerWithHeaderButtons = () => (
<Headers {...HeadingWithHeaderButtons} />
);
export const headerWithActions = () => <Headers {...HeadingWithActionButton} />;

const meta: Meta = {
Expand Down
JacquesLarique marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React from 'react';
import { ODS_BUTTON_SIZE, ODS_BUTTON_VARIANT } from '@ovhcloud/ods-components';
import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming';
import {
OsdsMenu,
OsdsMenuGroup,
OsdsMenuItem,
OsdsButton,
} from '@ovhcloud/ods-components/react';
import {
OdsHTMLAnchorElementRel,
OdsHTMLAnchorElementTarget,
} from '@ovhcloud/ods-common-core';
import { useOvhTracking } from '@ovh-ux/manager-react-shell-client';
import { useTranslation } from 'react-i18next';
import { Links, LinkType } from '../../../typography';
import '../translations/translation';
import GithubIcon from './changelog.icon';

export interface ChangelogLinks {
changelog: string;
roadmap: string;
'feature-request': string;
}

export interface ChangelogButtonProps {
links: ChangelogLinks;
chapters?: string[];
}

export const CHANGELOG_PREFIXES = ['tile-changelog-roadmap', 'external-link'];
const GO_TO = (link: string) => `go-to-${link}`;

export const ChangelogButton: React.FC<ChangelogButtonProps> = ({
links,
chapters = [],
}) => {
const { t } = useTranslation('buttons');
const { trackClick } = useOvhTracking();
return (
<>
<OsdsMenu>
<OsdsButton
slot="menu-title"
color={ODS_THEME_COLOR_INTENT.primary}
variant={ODS_BUTTON_VARIANT.ghost}
size={ODS_BUTTON_SIZE.sm}
className="whitespace-nowrap"
>
<span slot="start">
<GithubIcon />
</span>
{t('mrc_changelog_header')}
</OsdsButton>

{Object.entries(links).map(([key, link]) => {
return (
<OsdsMenuGroup key={key}>
<OsdsMenuItem>
<Links
href={link}
target={OdsHTMLAnchorElementTarget._blank}
rel={OdsHTMLAnchorElementRel.external}
type={LinkType.external}
label={t(`mrc_changelog_${key}`)}
onClickReturn={() =>
trackClick({
actionType: 'navigation',
actions: [...chapters, ...CHANGELOG_PREFIXES, GO_TO(key)],
})
}
/>
</OsdsMenuItem>
</OsdsMenuGroup>
);
})}
</OsdsMenu>
</>
);
};

export default ChangelogButton;
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const GithubIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0,0,256,256"
width="24px"
height="24px"
fill-rule="nonzero"
>
<g
fill="#0050d7"
fillRule="nonzero"
stroke="none"
strokeWidth="1"
strokeLinecap="butt"
strokeLinejoin="miter"
strokeMiterlimit="10"
strokeDasharray=""
strokeDashoffset="0"
fontFamily="none"
fontWeight="none"
fontSize="none"
textAnchor="none"
style={{ mixBlendMode: 'normal', height: '24px' }}
>
<g transform="scale(10.66667,10.66667)">
<path d="M10.9,2.1c-4.6,0.5 -8.3,4.2 -8.8,8.7c-0.5,4.7 2.2,8.9 6.3,10.5c0.3,0.1 0.6,-0.1 0.6,-0.5v-1.6c0,0 -0.4,0.1 -0.9,0.1c-1.4,0 -2,-1.2 -2.1,-1.9c-0.1,-0.4 -0.3,-0.7 -0.6,-1c-0.3,-0.1 -0.4,-0.1 -0.4,-0.2c0,-0.2 0.3,-0.2 0.4,-0.2c0.6,0 1.1,0.7 1.3,1c0.5,0.8 1.1,1 1.4,1c0.4,0 0.7,-0.1 0.9,-0.2c0.1,-0.7 0.4,-1.4 1,-1.8c-2.3,-0.5 -4,-1.8 -4,-4c0,-1.1 0.5,-2.2 1.2,-3c-0.1,-0.2 -0.2,-0.7 -0.2,-1.4c0,-0.4 0,-1 0.3,-1.6c0,0 1.4,0 2.8,1.3c0.5,-0.2 1.2,-0.3 1.9,-0.3c0.7,0 1.4,0.1 2,0.3c1.3,-1.3 2.8,-1.3 2.8,-1.3c0.2,0.6 0.2,1.2 0.2,1.6c0,0.8 -0.1,1.2 -0.2,1.4c0.7,0.8 1.2,1.8 1.2,3c0,2.2 -1.7,3.5 -4,4c0.6,0.5 1,1.4 1,2.3v2.6c0,0.3 0.3,0.6 0.7,0.5c3.7,-1.5 6.3,-5.1 6.3,-9.3c0,-6 -5.1,-10.7 -11.1,-10z"></path>
</g>
</g>
</svg>
);
};

export default GithubIcon;
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';
import { Meta } from '@storybook/react';
import {
ChangelogButton,
ChangelogButtonProps,
ChangelogLinks,
} from './changelog.component';

const changelogChapters: string[] = ['baremetal', 'server', 'dedicated'];
const changelogLinks: ChangelogLinks = {
roadmap:
'https://github.com/orgs/ovh/projects/16/views/1?pane=info&sliceBy%5Bvalue%5D=Baremetal',
changelog:
'https://github.com/orgs/ovh/projects/16/views/1?pane=info&sliceBy%5Bvalue%5D=Baremetal',
'feature-request':
'https://github.com/orgs/ovh/projects/16/views/1?pane=info&sliceBy%5Bvalue%5D=Baremetal',
};

export const changelogButton: ChangelogButtonProps = {
links: changelogLinks,
chapters: changelogChapters,
};

const meta: Meta<ChangelogButtonProps> = {
title: 'Navigation/Menus',
decorators: [(story) => <div>{story()}</div>],
component: ChangelogButton,
argTypes: {},
args: changelogButton,
};

export default meta;
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './action/action.component';
export * from './guide/guide.component';
export * from './changelog/changelog.component';
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{
"common_actions": "Aktionen",
"user_account_guides_header": "Anleitungen"
"user_account_guides_header": "Anleitungen",
"mrc_changelog_header": "Roadmap &amp; Changelog",
"mrc_changelog_roadmap": "Roadmap",
"mrc_changelog_changelog": "Changelog",
"mrc_changelog_feature-request": "Feature Request"
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{
"common_actions": "Actions",
"user_account_guides_header": "Guides"
"user_account_guides_header": "Guides",
"mrc_changelog_header": "Roadmap &amp; Changelog",
"mrc_changelog_roadmap": "Roadmap",
"mrc_changelog_changelog": "Changelog",
"mrc_changelog_feature-request": "Feature request"
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{
"common_actions": "Acciones",
"user_account_guides_header": "Guías"
"user_account_guides_header": "Guías",
"mrc_changelog_header": "Roadmap &amp; Changelog",
"mrc_changelog_roadmap": "Roadmap",
"mrc_changelog_changelog": "Changelog",
"mrc_changelog_feature-request": "Feature request"
}
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
{ "common_actions": "Actions", "user_account_guides_header": "Guides" }
{
"common_actions": "Actions",
"user_account_guides_header": "Guides",
"mrc_changelog_header": "Roadmap & Changelog",
"mrc_changelog_roadmap": "Roadmap",
"mrc_changelog_changelog": "Changelog",
"mrc_changelog_feature-request": "Feature request"
}
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
{ "common_actions": "Actions", "user_account_guides_header": "Guides" }
{
"common_actions": "Actions",
"user_account_guides_header": "Guides",
"mrc_changelog_header": "Roadmap & Changelog",
"mrc_changelog_roadmap": "Roadmap",
"mrc_changelog_changelog": "Changelog",
"mrc_changelog_feature-request": "Feature request"
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{
"common_actions": "Azioni",
"user_account_guides_header": "Guide"
"user_account_guides_header": "Guide",
"mrc_changelog_header": "Roadmap &amp; Changelog",
"mrc_changelog_roadmap": "Roadmap",
"mrc_changelog_changelog": "Changelog",
"mrc_changelog_feature-request": "Feature Request"
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{
"common_actions": "Operacje",
"user_account_guides_header": "Przewodniki"
"user_account_guides_header": "Przewodniki",
"mrc_changelog_header": "Roadmap &amp; Changelog",
"mrc_changelog_roadmap": "Roadmapa",
"mrc_changelog_changelog": "Changelog",
"mrc_changelog_feature-request": "Propozycja wdrożenia nowej funkcji"
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{
"common_actions": "Ações",
"user_account_guides_header": "Manuais"
"user_account_guides_header": "Manuais",
"mrc_changelog_header": "Roadmap &amp; Changelog",
"mrc_changelog_roadmap": "Roadmap",
"mrc_changelog_changelog": "Changelog",
"mrc_changelog_feature-request": "Feature request"
}
Loading