feat: Added CoursewareSearchResults UI component (#1224)
* feat: Added CoursewareSearchResults UI component * fix: Added conditional for undefined case instead of null * fix: Updated code to avoid mutation
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { Button, Icon } from '@edx/paragon';
|
||||
@@ -10,8 +10,11 @@ import { useElementBoundingBox, useLockScroll } from './hooks';
|
||||
import messages from './messages';
|
||||
|
||||
import CoursewareSearchForm from './CoursewareSearchForm';
|
||||
import CoursewareSearchResults from './CoursewareSearchResults';
|
||||
import mockedData from './test-data/mockedResults';
|
||||
|
||||
const CoursewareSearch = ({ intl, ...sectionProps }) => {
|
||||
const [results, setResults] = useState();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useLockScroll();
|
||||
@@ -19,6 +22,15 @@ const CoursewareSearch = ({ intl, ...sectionProps }) => {
|
||||
const info = useElementBoundingBox('courseTabsNavigation');
|
||||
const top = info ? `${Math.floor(info.top)}px` : 0;
|
||||
|
||||
const handleSubmit = (search) => {
|
||||
if (!search) {
|
||||
setResults(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
setResults(search.toLowerCase() !== 'lorem ipsum' ? mockedData : []);
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="courseware-search" style={{ '--modal-top-position': top }} data-testid="courseware-search-section" {...sectionProps}>
|
||||
<div className="courseware-search__close">
|
||||
@@ -32,60 +44,15 @@ const CoursewareSearch = ({ intl, ...sectionProps }) => {
|
||||
</Button>
|
||||
</div>
|
||||
<div className="courseware-search__outer-content">
|
||||
<div className="courseware-search__content" style={{ height: '999px' }}>
|
||||
<div className="courseware-search__content">
|
||||
<h2>{intl.formatMessage(messages.searchModuleTitle)}</h2>
|
||||
<CoursewareSearchForm
|
||||
onSubmit={handleSubmit}
|
||||
placeholder={intl.formatMessage(messages.searchBarPlaceholderText)}
|
||||
/>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis semper rutrum odio quis congue.
|
||||
Duis sodales nibh et sapien elementum fermentum. Quisque magna urna, gravida at gravida et,
|
||||
ultricies vel massa.Aliquam in vehicula dolor, id scelerisque felis.
|
||||
Morbi posuere scelerisque tincidunt. Proin et gravida tortor. Vestibulum vel orci vulputate,
|
||||
gravida justo eu, varius dolor. Etiam viverra diam sed est tincidunt, et aliquam est efficitur.
|
||||
Donec imperdiet eros quis est condimentum faucibus.
|
||||
</p>
|
||||
<p>
|
||||
In mattis, tellus ut lacinia viverra, ligula ex sagittis ex, sed mollis ex enim ut velit.
|
||||
Nunc elementum, risus eget feugiat scelerisque, sapien felis laoreet nisl, ut pharetra neque
|
||||
lorem a elit. Maecenas elementum, metus fringilla suscipit imperdiet, mi nunc efficitur elit,
|
||||
sed consequat massa magna sit amet dui. Curabitur ultrices nisi vel lorem scelerisque, pharetra
|
||||
luctus nunc pulvinar. Morbi aliquam ante eget arcu condimentum consectetur. Fusce faucibus lacus
|
||||
sed pretium ultrices. Curabitur neque lacus, elementum convallis augue placerat, gravida
|
||||
scelerisque ipsum. Donec bibendum lectus id ullamcorper sodales. Integer quis ante facilisis erat
|
||||
maximus viverra. Nunc rutrum posuere lectus, aliquam congue odio blandit nec. Phasellus placerat,
|
||||
magna non bibendum lacinia, tortor orci vulputate dui, vitae imperdiet turpis dui nec tortor.
|
||||
Praesent porttitor mollis diam ut gravida. Praesent vitae felis dignissim sem accumsan dignissim.
|
||||
Fusce ullamcorper bibendum ante ac pellentesque. Aliquam sed leo vel leo pellentesque cursus a at risus.
|
||||
Donec sollicitudin maximus diam, sit amet molestie sapien commodo at.
|
||||
</p>
|
||||
<p>
|
||||
Cras ornare pulvinar est id rhoncus. Aenean ut risus magna. Fusce cursus pulvinar dui ut egestas.
|
||||
Quisque condimentum risus non mi sagittis, eu facilisis enim hendrerit. Integer faucibus dapibus rutrum.
|
||||
Nullam vitae mollis tortor, eu lacinia mi. Nunc commodo ex id eros hendrerit, vel interdum augue tristique.
|
||||
Suspendisse ullamcorper, purus in vestibulum auctor, justo nisi finibus dolor,
|
||||
nec dignissim arcu enim a augue.
|
||||
</p>
|
||||
<p>
|
||||
Fusce vel libero odio. Orci varius natoque penatibus et magnis dis parturient montes,
|
||||
nascetur ridiculus mus. Pellentesque at varius turpis. Ut pulvinar efficitur congue. Vivamus cursus,
|
||||
purus at aliquet malesuada, felis quam blandit dolor, a interdum justo est semper augue.
|
||||
In eu lectus sit amet est pellentesque porta vel eget magna. Morbi sollicitudin turpis vitae faucibus
|
||||
pulvinar. Etiam placerat pulvinar porta.
|
||||
</p>
|
||||
<p>
|
||||
Suspendisse mattis eget felis non sagittis. Nulla facilisi. In bibendum cursus purus, non venenatis tellus
|
||||
dignissim sit amet. Phasellus volutpat ipsum turpis, non imperdiet nisi elementum a. Nunc mollis, sapien
|
||||
cursus vehicula consectetur, nunc turpis pulvinar mauris, at varius justo mi egestas nisi. Fusce semper
|
||||
sapien in orci rhoncus ornare. Donec maximus mi eu pulvinar convallis.
|
||||
</p>
|
||||
<p>
|
||||
Nullam tortor sem, hendrerit eu sapien ac, venenatis rhoncus ligula. Donec nibh leo, venenatis sed interdum
|
||||
ac, pharetra sed nibh. Orci varius natoque penatibus et magnis dis parturient montes,
|
||||
nascetur ridiculus mus. Sed congue risus eu mattis condimentum. In id nulla sit amet magna suscipit
|
||||
consectetur. Nullam vitae augue felis. In consequat tempus diam, a eleifend ante bibendum ac.
|
||||
Vivamus mi orci, fermentum ac viverra quis, tristique a ipsum. Morbi imperdiet porta sem, in sollicitudin
|
||||
risus dignissim at. Nulla dapibus iaculis vestibulum.
|
||||
</p>
|
||||
{results !== undefined ? (
|
||||
<CoursewareSearchResults results={results} />
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import React from 'react';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import {
|
||||
Folder, TextFields, VideoCamera, Article,
|
||||
} from '@edx/paragon/icons';
|
||||
import { Icon } from '@edx/paragon';
|
||||
import PropTypes from 'prop-types';
|
||||
import messages from './messages';
|
||||
|
||||
const iconTypeMapping = {
|
||||
document: Folder,
|
||||
text: TextFields,
|
||||
video: VideoCamera,
|
||||
};
|
||||
const defaultIcon = Article;
|
||||
|
||||
const CoursewareSearchResults = ({ intl, results }) => {
|
||||
if (!results?.length) {
|
||||
return (
|
||||
<div className="courseware-search-results">
|
||||
<p className="courseware-search-results__empty" data-testid="no-results">{intl.formatMessage(messages.searchResultsNone)}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="courseware-search-results" data-testid="search-results">
|
||||
{results.map(({
|
||||
title, href, type, breadcrumbs, contentMatches, isExternal,
|
||||
}) => {
|
||||
const key = type.toLowerCase();
|
||||
const icon = iconTypeMapping[key] || defaultIcon;
|
||||
|
||||
const linkProps = isExternal ? {
|
||||
href,
|
||||
target: '_blank',
|
||||
rel: 'nofollow',
|
||||
} : { href };
|
||||
|
||||
return (
|
||||
<a className="courseware-search-results__item" {...linkProps}>
|
||||
<div className="courseware-search-results__icon"><Icon src={icon} /></div>
|
||||
<div className="courseware-search-results__info">
|
||||
<div className="courseware-search-results__title">
|
||||
<span>{title}</span>
|
||||
{contentMatches ? (<em>{contentMatches}</em>) : null }
|
||||
</div>
|
||||
{breadcrumbs?.length ? (
|
||||
<ul className="courseware-search-results__breadcrumbs">
|
||||
{breadcrumbs.map(bc => (<li><div>{bc}</div></li>))}
|
||||
</ul>
|
||||
) : null}
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
CoursewareSearchResults.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
results: PropTypes.arrayOf(PropTypes.objectOf({
|
||||
title: PropTypes.string.isRequired,
|
||||
href: PropTypes.string.isRequired,
|
||||
type: PropTypes.string,
|
||||
breadcrumbs: PropTypes.arrayOf(PropTypes.string),
|
||||
contentMatches: PropTypes.number,
|
||||
isExternal: PropTypes.bool,
|
||||
})),
|
||||
};
|
||||
|
||||
CoursewareSearchResults.defaultProps = {
|
||||
results: [],
|
||||
};
|
||||
|
||||
export default injectIntl(CoursewareSearchResults);
|
||||
@@ -0,0 +1,38 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
initializeMockApp,
|
||||
render,
|
||||
screen,
|
||||
} from '../../setupTest';
|
||||
import CoursewareSearchResults from './CoursewareSearchResults';
|
||||
import messages from './messages';
|
||||
import mockedData from './test-data/mockedResults';
|
||||
|
||||
jest.mock('react-redux');
|
||||
|
||||
function renderComponent({ results }) {
|
||||
const { container } = render(<CoursewareSearchResults results={results} />);
|
||||
return container;
|
||||
}
|
||||
|
||||
describe('CoursewareSearchResults', () => {
|
||||
beforeAll(async () => {
|
||||
initializeMockApp();
|
||||
});
|
||||
|
||||
describe('when an empty array is provided', () => {
|
||||
beforeEach(() => { renderComponent({ results: [] }); });
|
||||
|
||||
it('should render a "no results found" message.', () => {
|
||||
expect(screen.getByTestId('no-results').textContent).toBe(messages.searchResultsNone.defaultMessage);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when list of results is provided', () => {
|
||||
beforeEach(() => { renderComponent({ results: mockedData }); });
|
||||
|
||||
it('should match the snapshot', () => {
|
||||
expect(screen.getByTestId('search-results')).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,513 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CoursewareSearchResults when list of results is provided should match the snapshot 1`] = `
|
||||
<div
|
||||
class="courseware-search-results"
|
||||
data-testid="search-results"
|
||||
>
|
||||
<a
|
||||
class="courseware-search-results__item"
|
||||
href="https://www.edx.org/"
|
||||
rel="nofollow"
|
||||
target="_blank"
|
||||
>
|
||||
<div
|
||||
class="courseware-search-results__icon"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M10 4H2v16h20V6H12l-2-2z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="courseware-search-results__info"
|
||||
>
|
||||
<div
|
||||
class="courseware-search-results__title"
|
||||
>
|
||||
<span>
|
||||
A Comprehensive Introduction to Supply Chain Analytics
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<a
|
||||
class="courseware-search-results__item"
|
||||
href="https://www.edx.org/"
|
||||
rel="nofollow"
|
||||
target="_blank"
|
||||
>
|
||||
<div
|
||||
class="courseware-search-results__icon"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M10 4H2v16h20V6H12l-2-2z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="courseware-search-results__info"
|
||||
>
|
||||
<div
|
||||
class="courseware-search-results__title"
|
||||
>
|
||||
<span>
|
||||
Basics of Data Collection for Supply Chain Analytics: Exploring Methods and Techniques for Optimal Data Gathering
|
||||
</span>
|
||||
</div>
|
||||
<ul
|
||||
class="courseware-search-results__breadcrumbs"
|
||||
>
|
||||
<li>
|
||||
<div>
|
||||
A Comprehensive Introduction to Supply Chain Analytics
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</a>
|
||||
<a
|
||||
class="courseware-search-results__item"
|
||||
href="/"
|
||||
>
|
||||
<div
|
||||
class="courseware-search-results__icon"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M10 4H2v16h20V6H12l-2-2z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="courseware-search-results__info"
|
||||
>
|
||||
<div
|
||||
class="courseware-search-results__title"
|
||||
>
|
||||
<span>
|
||||
Zero-Waste Strategies in Supply Chain Management
|
||||
</span>
|
||||
</div>
|
||||
<ul
|
||||
class="courseware-search-results__breadcrumbs"
|
||||
>
|
||||
<li>
|
||||
<div>
|
||||
A Comprehensive Introduction to Supply Chain Analytics
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
Basics of Data Collection for Supply Chain Analytics: Exploring Methods and Techniques for Optimal Data Gathering
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</a>
|
||||
<a
|
||||
class="courseware-search-results__item"
|
||||
href="/"
|
||||
>
|
||||
<div
|
||||
class="courseware-search-results__icon"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M2.5 4v3h5v12h3V7h5V4h-13zm19 5h-9v3h3v7h3v-7h3V9z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="courseware-search-results__info"
|
||||
>
|
||||
<div
|
||||
class="courseware-search-results__title"
|
||||
>
|
||||
<span>
|
||||
Addressing Overproduction and Excess Inventory in Supply Chains
|
||||
</span>
|
||||
</div>
|
||||
<ul
|
||||
class="courseware-search-results__breadcrumbs"
|
||||
>
|
||||
<li>
|
||||
<div>
|
||||
A Comprehensive Introduction to Supply Chain Analytics
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
Basics of Data Collection for Supply Chain Analytics: Exploring Methods and Techniques for Optimal Data Gathering
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
Zero-Waste Strategies in Supply Chain Management
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</a>
|
||||
<a
|
||||
class="courseware-search-results__item"
|
||||
href="/"
|
||||
>
|
||||
<div
|
||||
class="courseware-search-results__icon"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M2.5 4v3h5v12h3V7h5V4h-13zm19 5h-9v3h3v7h3v-7h3V9z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="courseware-search-results__info"
|
||||
>
|
||||
<div
|
||||
class="courseware-search-results__title"
|
||||
>
|
||||
<span>
|
||||
Balancing Supply and Demand
|
||||
</span>
|
||||
<em>
|
||||
9
|
||||
</em>
|
||||
</div>
|
||||
<ul
|
||||
class="courseware-search-results__breadcrumbs"
|
||||
>
|
||||
<li>
|
||||
<div>
|
||||
Strategic Sourcing and Its Impact on Supply-Demand Balance
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
Dealing with Over-supply and Under-supply Situations
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
Scenario Planning for Uncertain Supply-Demand Conditions
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</a>
|
||||
<a
|
||||
class="courseware-search-results__item"
|
||||
href="/"
|
||||
>
|
||||
<div
|
||||
class="courseware-search-results__icon"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M2.5 4v3h5v12h3V7h5V4h-13zm19 5h-9v3h3v7h3v-7h3V9z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="courseware-search-results__info"
|
||||
>
|
||||
<div
|
||||
class="courseware-search-results__title"
|
||||
>
|
||||
<span>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ornare porttitor purus, eget vehicula lorem ullamcorper in. In pellentesque vehicula diam, eget efficitur nisl aliquet id. Donec tincidunt dictum odio quis placerat.
|
||||
</span>
|
||||
<em>
|
||||
6
|
||||
</em>
|
||||
</div>
|
||||
<ul
|
||||
class="courseware-search-results__breadcrumbs"
|
||||
>
|
||||
<li>
|
||||
<div>
|
||||
Section name
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
Subsection name
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
Unit name
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</a>
|
||||
<a
|
||||
class="courseware-search-results__item"
|
||||
href="/"
|
||||
>
|
||||
<div
|
||||
class="courseware-search-results__icon"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M17 10.5V6H3v12h14v-4.5l4 4v-11l-4 4Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="courseware-search-results__info"
|
||||
>
|
||||
<div
|
||||
class="courseware-search-results__title"
|
||||
>
|
||||
<span>
|
||||
TextSupply chain toolbox
|
||||
</span>
|
||||
</div>
|
||||
<ul
|
||||
class="courseware-search-results__breadcrumbs"
|
||||
>
|
||||
<li>
|
||||
<div>
|
||||
Section name
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
Subsection name
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
Unit name
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</a>
|
||||
<a
|
||||
class="courseware-search-results__item"
|
||||
href="/"
|
||||
>
|
||||
<div
|
||||
class="courseware-search-results__icon"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M17 10.5V6H3v12h14v-4.5l4 4v-11l-4 4Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="courseware-search-results__info"
|
||||
>
|
||||
<div
|
||||
class="courseware-search-results__title"
|
||||
>
|
||||
<span>
|
||||
Utilizing Demand-Driven Strategies
|
||||
</span>
|
||||
<em>
|
||||
20
|
||||
</em>
|
||||
</div>
|
||||
<ul
|
||||
class="courseware-search-results__breadcrumbs"
|
||||
>
|
||||
<li>
|
||||
<div>
|
||||
Section name
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
Subsection name
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
Unit name
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</a>
|
||||
<a
|
||||
class="courseware-search-results__item"
|
||||
href="/"
|
||||
>
|
||||
<div
|
||||
class="courseware-search-results__icon"
|
||||
>
|
||||
<span
|
||||
class="pgn__icon"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
focusable="false"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M17 10.5V6H3v12h14v-4.5l4 4v-11l-4 4Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="courseware-search-results__info"
|
||||
>
|
||||
<div
|
||||
class="courseware-search-results__title"
|
||||
>
|
||||
<span>
|
||||
Video
|
||||
</span>
|
||||
<em>
|
||||
1
|
||||
</em>
|
||||
</div>
|
||||
<ul
|
||||
class="courseware-search-results__breadcrumbs"
|
||||
>
|
||||
<li>
|
||||
<div>
|
||||
Section name
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
Subsection name
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
Unit name
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
`;
|
||||
@@ -34,6 +34,101 @@
|
||||
}
|
||||
}
|
||||
|
||||
.courseware-search-results {
|
||||
margin-top: 1.5rem;
|
||||
|
||||
&__empty {
|
||||
color: $gray-500;
|
||||
}
|
||||
|
||||
&__item {
|
||||
display: block;
|
||||
padding: .75rem 1rem;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
gap: 0.625rem;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
background: $light-300;
|
||||
}
|
||||
|
||||
&:not(:first-child) {
|
||||
border-top: 1px solid $light-300;
|
||||
}
|
||||
}
|
||||
|
||||
&__icon {
|
||||
padding: 0.375rem 0 0 0.375rem;
|
||||
color: $gray-300;
|
||||
}
|
||||
|
||||
&__info {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&__title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 2.5;
|
||||
font-size: 0.875rem;
|
||||
color: $black;
|
||||
|
||||
> span {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
em {
|
||||
padding: 0.125rem 0.375rem;
|
||||
font-variant-numeric: lining-nums tabular-nums;
|
||||
min-width: 1.25rem;
|
||||
line-height: 1rem;
|
||||
background: $light-300;
|
||||
border-radius: 99rem;
|
||||
font-style: normal;
|
||||
margin-left: 0.375rem;
|
||||
font-size: 0.6875rem;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
&__breadcrumbs {
|
||||
display: flex;
|
||||
gap: 1.25rem;
|
||||
color: $gray-400;
|
||||
overflow: hidden;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
> li {
|
||||
position: relative;
|
||||
flex-shrink: 1;
|
||||
min-width: 0;
|
||||
|
||||
&:not(:first-child)::before {
|
||||
content: '›';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -55%);
|
||||
left: -0.625rem;
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
font-size: 0.75rem;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: map-get($grid-breakpoints, 'md')) {
|
||||
.courseware-search__content {
|
||||
padding-top: 8rem;
|
||||
|
||||
@@ -21,6 +21,11 @@ const messages = defineMessages({
|
||||
defaultMessage: 'Search',
|
||||
description: 'Placeholder text for the Courseware Search input control',
|
||||
},
|
||||
searchResultsNone: {
|
||||
id: 'learn.coursewareSerch.searchResultsNone',
|
||||
defaultMessage: 'No results found.',
|
||||
description: 'Text to show when the Courseware Search found no results matching the criteria.',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
|
||||
66
src/course-home/courseware-search/test-data/mockedResults.js
Normal file
66
src/course-home/courseware-search/test-data/mockedResults.js
Normal file
@@ -0,0 +1,66 @@
|
||||
// Test data for testing the CoursewareSearchResults UI component.
|
||||
|
||||
const mockedResults = [{
|
||||
type: 'document',
|
||||
title: 'A Comprehensive Introduction to Supply Chain Analytics',
|
||||
href: 'https://www.edx.org/',
|
||||
isExternal: true,
|
||||
}, {
|
||||
type: 'document',
|
||||
title: 'Basics of Data Collection for Supply Chain Analytics: Exploring Methods and Techniques for Optimal Data Gathering',
|
||||
breadcrumbs: ['A Comprehensive Introduction to Supply Chain Analytics'],
|
||||
href: 'https://www.edx.org/',
|
||||
isExternal: true,
|
||||
}, {
|
||||
type: 'document',
|
||||
title: 'Zero-Waste Strategies in Supply Chain Management',
|
||||
breadcrumbs: [
|
||||
'A Comprehensive Introduction to Supply Chain Analytics',
|
||||
'Basics of Data Collection for Supply Chain Analytics: Exploring Methods and Techniques for Optimal Data Gathering',
|
||||
],
|
||||
href: '/',
|
||||
}, {
|
||||
type: 'text',
|
||||
title: 'Addressing Overproduction and Excess Inventory in Supply Chains',
|
||||
breadcrumbs: [
|
||||
'A Comprehensive Introduction to Supply Chain Analytics',
|
||||
'Basics of Data Collection for Supply Chain Analytics: Exploring Methods and Techniques for Optimal Data Gathering',
|
||||
'Zero-Waste Strategies in Supply Chain Management',
|
||||
],
|
||||
href: '/',
|
||||
}, {
|
||||
type: 'text',
|
||||
title: 'Balancing Supply and Demand',
|
||||
breadcrumbs: [
|
||||
'Strategic Sourcing and Its Impact on Supply-Demand Balance',
|
||||
'Dealing with Over-supply and Under-supply Situations',
|
||||
'Scenario Planning for Uncertain Supply-Demand Conditions',
|
||||
],
|
||||
contentMatches: 9,
|
||||
href: '/',
|
||||
}, {
|
||||
type: 'text',
|
||||
title: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ornare porttitor purus, eget vehicula lorem ullamcorper in. In pellentesque vehicula diam, eget efficitur nisl aliquet id. Donec tincidunt dictum odio quis placerat.',
|
||||
breadcrumbs: ['Section name', 'Subsection name', 'Unit name'],
|
||||
contentMatches: 6,
|
||||
href: '/',
|
||||
}, {
|
||||
type: 'video',
|
||||
title: 'TextSupply chain toolbox',
|
||||
breadcrumbs: ['Section name', 'Subsection name', 'Unit name'],
|
||||
href: '/',
|
||||
}, {
|
||||
type: 'video',
|
||||
title: 'Utilizing Demand-Driven Strategies',
|
||||
breadcrumbs: ['Section name', 'Subsection name', 'Unit name'],
|
||||
contentMatches: 20,
|
||||
href: '/',
|
||||
}, {
|
||||
type: 'video',
|
||||
title: 'Video',
|
||||
breadcrumbs: ['Section name', 'Subsection name', 'Unit name'],
|
||||
contentMatches: 1,
|
||||
href: '/',
|
||||
}];
|
||||
|
||||
export default mockedResults;
|
||||
Reference in New Issue
Block a user