Skip to content

Commit

Permalink
fix(breadcrumb): reset is-last attribute on new items setup
Browse files Browse the repository at this point in the history
  • Loading branch information
dpellier committed Oct 28, 2024
1 parent 0e21361 commit b86f8f2
Show file tree
Hide file tree
Showing 17 changed files with 238 additions and 18 deletions.
1 change: 1 addition & 0 deletions packages/examples/react-webpack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"formik": "2.4.6",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-router": "6.27.0",
"yup": "1.4.0"
},
"devDependencies": {
Expand Down
1 change: 0 additions & 1 deletion packages/examples/react-webpack/src/app/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,3 @@
.app {
font-family: var(--ods-font-family-default);
}

19 changes: 15 additions & 4 deletions packages/examples/react-webpack/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
import React from 'react';
import { createRoot } from 'react-dom/client';
import { App } from 'app/App';
import { BrowserRouter } from 'react-router-dom';
// import { App } from 'app/App';
import { RouterApp } from 'router-app/RouterApp';
// import '@ovhcloud/ods-themes/dark';
import '@ovhcloud/ods-themes/default';

const appElement = document.getElementById('app');
const root = createRoot(appElement!);

function renderApp() {
// function renderApp() {
// root.render(
// <App />,
// );
// }

function renderRouterApp() {
root.render(
<App />,
<BrowserRouter>
<RouterApp />
</BrowserRouter>
);
}

renderApp();
//renderApp();
renderRouterApp();
21 changes: 21 additions & 0 deletions packages/examples/react-webpack/src/router-app/RouterApp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React, { type ReactElement } from 'react';
import { Navigate, Route, Routes } from 'react-router-dom';
import { Breadcrumb } from 'router-app/components/breadcrumb/Breadcrumb';
import { ROUTE } from 'router-app/constants/navigation';
import { Products } from 'router-app/modules/products/Products';
import styles from './routerApp.scss';

function RouterApp(): ReactElement {
return (
<div className={ styles['router-app'] }>
<Breadcrumb />

<Routes>
<Route path={ `${ROUTE.products}/*` } element={ <Products /> } />
<Route path="*" element={ <Navigate to={ ROUTE.products } replace /> } />
</Routes>
</div>
);
}

export { RouterApp };
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { OdsBreadcrumb, OdsBreadcrumbItem } from '@ovhcloud/ods-components/react';
import React, { type ReactElement, useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';
import styles from './breadcrumb.scss';

function Breadcrumb (): ReactElement {
const location = useLocation();
const [items, setItems] = useState<any[]>([]);

useEffect(() => {
const pathParts = location.pathname.split('/').filter(Boolean);
let lastPath = '';

setItems(pathParts.map((pathPart) => {
lastPath += `/${pathPart}`;

return {
href: lastPath,
label: pathPart,
};
}));
}, [location.pathname]);

return (
<OdsBreadcrumb>
{
items.map((item: any) => (
<OdsBreadcrumbItem className={ styles['breadcrumb__item'] }
key={ item.href }
href={ item.href }
label={ item.label } />
))
}
</OdsBreadcrumb>
);
}

export { Breadcrumb };
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.breadcrumb {
&__item {
text-transform: capitalize;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
enum ROUTE {
products = '/products'
}

export {
ROUTE,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React, { type ReactElement } from 'react';
import { Navigate, Route, Routes } from 'react-router-dom';
import { ROUTE } from 'router-app/constants/navigation';
import { Home } from 'router-app/modules/products/modules/home/Home';
import { List } from 'router-app/modules/products/modules/list/List';
import { View } from 'router-app/modules/products/modules/view/View';

function Products(): ReactElement {
return (
<Routes>
<Route path="list" element={ <List /> } />
<Route path="list/*" element={ <View /> } />
<Route index element={ <Home /> } />
<Route path="*" element={ <Navigate to={ ROUTE.products } replace /> } />
</Routes>
);
}

export { Products };
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React, { type ReactElement } from 'react';
import { Link } from 'react-router-dom';
import { ROUTE } from 'router-app/constants/navigation';

function Home(): ReactElement {
return (
<div>
<h1>
Products Home Page
</h1>

<Link to={ `${ROUTE.products}/list` }>
Go to list page
</Link>
</div>
);
}

export { Home };
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React, { type ReactElement } from 'react';
import { Link } from 'react-router-dom';
import { ROUTE } from 'router-app/constants/navigation';

function List(): ReactElement {
return (
<div>
<h1>
Products List Page
</h1>

<Link to={ ROUTE.products }>
Back
</Link>

<br />

<Link to={ `${ROUTE.products}/list/product1` }>
View product 1
</Link>

<br />

<Link to={ `${ROUTE.products}/list/product2` }>
View product 2
</Link>
</div>
);
}

export { List };
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React, { type ReactElement } from 'react';
import { Link } from 'react-router-dom';
import { ROUTE } from 'router-app/constants/navigation';

function View(): ReactElement {
return (
<div>
<h1>
Products View Page
</h1>

<Link to={ `${ROUTE.products}/list` }>
Back
</Link>
</div>
);
}

export { View };
5 changes: 5 additions & 0 deletions packages/examples/react-webpack/src/router-app/routerApp.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// @import '@ovhcloud/ods-components/style';

.router-app {
font-family: var(--ods-font-family-default);
}
3 changes: 2 additions & 1 deletion packages/examples/react-webpack/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"noUnusedParameters": true,
"outDir": "dist",
"paths": {
"app/*": ["src/app/*"]
"app/*": ["src/app/*"],
"router-app/*": ["src/router-app/*"]
},
"removeComments": true,
"sourceMap": true,
Expand Down
1 change: 1 addition & 0 deletions packages/examples/react-webpack/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ module.exports = (env, options) => {
resolve: {
alias: {
app: path.resolve(__dirname, 'src/app/'),
'router-app': path.resolve(__dirname, 'src/router-app/'),
},
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ function expandItems(items: Element[]): void {

function setupItems(items: Element[]): void {
const breadcrumbItems = items
.filter((child) => child.tagName.toLowerCase() === 'ods-breadcrumb-item');
.filter((child) => child.tagName.toLowerCase() === 'ods-breadcrumb-item')
.map((child) => {
child.removeAttribute('is-last');
return child;
});

if (breadcrumbItems.length) {
breadcrumbItems[breadcrumbItems.length - 1].setAttribute('is-last', 'true');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,17 @@ type TestItem = {
'is-expandable'?: string,
'is-last'?: string,
tagName: string,
removeAttribute: jest.Mock,
setAttribute: jest.Mock,
}

describe('ods-breadcrumb controller', () => {
const removeAttributeSpy = jest.fn()
.mockImplementation(function(attr) {
// @ts-ignore "this" is the actual item
delete this[attr];
});

const setAttributeSpy = jest.fn()
.mockImplementation(function(attr, value) {
// @ts-ignore "this" is the actual item
Expand All @@ -20,9 +27,9 @@ describe('ods-breadcrumb controller', () => {
describe('expandItems', () => {
it('should update the attributes of ods-breadcrumb-item only', () => {
const dummyItems: TestItem[] = [
{ setAttribute: setAttributeSpy, tagName: 'ODS-BREADCRUMB-ITEM' },
{ setAttribute: setAttributeSpy, tagName: 'ODS-BUTTON' },
{ setAttribute: setAttributeSpy, tagName: 'ODS-BREADCRUMB-ITEM' },
{ removeAttribute: removeAttributeSpy, setAttribute: setAttributeSpy, tagName: 'ODS-BREADCRUMB-ITEM' },
{ removeAttribute: removeAttributeSpy, setAttribute: setAttributeSpy, tagName: 'ODS-BUTTON' },
{ removeAttribute: removeAttributeSpy, setAttribute: setAttributeSpy, tagName: 'ODS-BREADCRUMB-ITEM' },
];

// @ts-ignore for test purpose
Expand All @@ -38,11 +45,11 @@ describe('ods-breadcrumb controller', () => {
});
});

describe('expandItems', () => {
describe('setupItems', () => {
it('should do nothing if there are no ods-breadcrumb-item', () => {
const dummyItems: TestItem[] = [
{ setAttribute: setAttributeSpy, tagName: 'ODS-BUTTON' },
{ setAttribute: setAttributeSpy, tagName: 'SPAN' },
{ removeAttribute: removeAttributeSpy, setAttribute: setAttributeSpy, tagName: 'ODS-BUTTON' },
{ removeAttribute: removeAttributeSpy, setAttribute: setAttributeSpy, tagName: 'SPAN' },
];

// @ts-ignore for test purpose
Expand All @@ -53,11 +60,11 @@ describe('ods-breadcrumb controller', () => {

it('should setup the ods-breadcrumb-item attributes', () => {
const dummyItems: TestItem[] = [
{ setAttribute: setAttributeSpy, tagName: 'ODS-BREADCRUMB-ITEM' },
{ setAttribute: setAttributeSpy, tagName: 'ODS-BREADCRUMB-ITEM' },
{ setAttribute: setAttributeSpy, tagName: 'ODS-BREADCRUMB-ITEM' },
{ setAttribute: setAttributeSpy, tagName: 'ODS-BREADCRUMB-ITEM' },
{ setAttribute: setAttributeSpy, tagName: 'ODS-BREADCRUMB-ITEM' },
{ removeAttribute: removeAttributeSpy, setAttribute: setAttributeSpy, tagName: 'ODS-BREADCRUMB-ITEM' },
{ removeAttribute: removeAttributeSpy, setAttribute: setAttributeSpy, tagName: 'ODS-BREADCRUMB-ITEM' },
{ removeAttribute: removeAttributeSpy, setAttribute: setAttributeSpy, tagName: 'ODS-BREADCRUMB-ITEM' },
{ removeAttribute: removeAttributeSpy, setAttribute: setAttributeSpy, tagName: 'ODS-BREADCRUMB-ITEM' },
{ removeAttribute: removeAttributeSpy, setAttribute: setAttributeSpy, tagName: 'ODS-BREADCRUMB-ITEM' },
];

// @ts-ignore for test purpose
Expand All @@ -80,5 +87,18 @@ describe('ods-breadcrumb controller', () => {
expect(dummyItems[4]['is-expandable']).toBeUndefined();
expect(dummyItems[4]['is-last']).toBe('true');
});

it('should reset the "is-last" attribute correctly', () => {
const dummyItems: TestItem[] = [
{ ['is-last']: 'true', removeAttribute: removeAttributeSpy, setAttribute: setAttributeSpy, tagName: 'ODS-BREADCRUMB-ITEM' },
{ removeAttribute: removeAttributeSpy, setAttribute: setAttributeSpy, tagName: 'ODS-BREADCRUMB-ITEM' },
];

// @ts-ignore for test purpose
setupItems(dummyItems);

expect(dummyItems[0]['is-last']).toBeUndefined();
expect(dummyItems[1]['is-last']).toBe('true');
});
});
});
19 changes: 19 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4477,6 +4477,13 @@ __metadata:
languageName: node
linkType: hard

"@remix-run/router@npm:1.20.0":
version: 1.20.0
resolution: "@remix-run/router@npm:1.20.0"
checksum: 6bff41117eabb867b17c89baa727580f0a431368b309cd9a1f69767aafa68ea9cac95ff0eeb86d37c2c8655f5cd7c6283d37ae5e6d93e94f648c6112ddb24ede
languageName: node
linkType: hard

"@rollup/rollup-android-arm-eabi@npm:4.13.0":
version: 4.13.0
resolution: "@rollup/rollup-android-arm-eabi@npm:4.13.0"
Expand Down Expand Up @@ -18692,6 +18699,17 @@ __metadata:
languageName: node
linkType: hard

"react-router@npm:6.27.0":
version: 6.27.0
resolution: "react-router@npm:6.27.0"
dependencies:
"@remix-run/router": 1.20.0
peerDependencies:
react: ">=16.8"
checksum: d22eedc33bcb11891b431655f90eed2d52c2fb3165ad11ca625f62970caf59c4859e6b1a3f92e78902b31ff1a8b2482ebf97ddebb82e9687d1f98730c14e04e6
languageName: node
linkType: hard

"react-webpack@workspace:packages/examples/react-webpack":
version: 0.0.0-use.local
resolution: "react-webpack@workspace:packages/examples/react-webpack"
Expand All @@ -18711,6 +18729,7 @@ __metadata:
postcss-loader: 8.1.0
react: 18.2.0
react-dom: 18.2.0
react-router: 6.27.0
resolve-url-loader: 5.0.0
sass: 1.71.0
sass-loader: 14.1.0
Expand Down

0 comments on commit b86f8f2

Please sign in to comment.