feat: Allow selecting my multiple filters in video gallery
The sort and filter UI of the video gallery was not working, this fixes that issue, and also adds a new UI for filering videos that allows filtering videos to include more than one status. It also fixes the hooks related to VideoGallery to avoid potential bugs in the future and updates tests to use react testing library instead of enzyme. It also reduces the padding in gallery page.
This commit is contained in:
@@ -7,15 +7,13 @@ import {
|
||||
|
||||
import {
|
||||
FormattedMessage,
|
||||
injectIntl,
|
||||
intlShape,
|
||||
useIntl,
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
|
||||
import messages from './messages';
|
||||
import GalleryCard from './GalleryCard';
|
||||
|
||||
export const Gallery = ({
|
||||
show,
|
||||
galleryIsEmpty,
|
||||
searchIsEmpty,
|
||||
displayList,
|
||||
@@ -25,12 +23,8 @@ export const Gallery = ({
|
||||
showIdsOnCards,
|
||||
height,
|
||||
isLoaded,
|
||||
// injected
|
||||
intl,
|
||||
}) => {
|
||||
if (!show) {
|
||||
return null;
|
||||
}
|
||||
const intl = useIntl();
|
||||
if (!isLoaded) {
|
||||
return (
|
||||
<div style={{
|
||||
@@ -96,8 +90,6 @@ Gallery.propTypes = {
|
||||
emptyGalleryLabel: PropTypes.shape({}).isRequired,
|
||||
showIdsOnCards: PropTypes.bool,
|
||||
height: PropTypes.string,
|
||||
// injected
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(Gallery);
|
||||
export default Gallery;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { formatMessage } from '../../../testUtils';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { Gallery } from './Gallery';
|
||||
|
||||
jest.mock('../../data/redux', () => ({
|
||||
@@ -18,28 +19,28 @@ describe('TextEditor Image Gallery component', () => {
|
||||
describe('component', () => {
|
||||
const props = {
|
||||
galleryIsEmpty: false,
|
||||
emptyGalleryLabel: {
|
||||
id: 'emptyGalleryMsg',
|
||||
defaultMessage: 'Empty Gallery',
|
||||
},
|
||||
searchIsEmpty: false,
|
||||
displayList: [{ id: 1 }, { id: 2 }, { id: 3 }],
|
||||
highlighted: 'props.highlighted',
|
||||
onHighlightChange: jest.fn().mockName('props.onHighlightChange'),
|
||||
intl: { formatMessage },
|
||||
isLoaded: true,
|
||||
};
|
||||
const shallowWithIntl = (component) => shallow(<IntlProvider locale="en">{component}</IntlProvider>);
|
||||
test('snapshot: not loaded, show spinner', () => {
|
||||
expect(shallow(<Gallery {...props} isLoaded={false} />)).toMatchSnapshot();
|
||||
expect(shallowWithIntl(<Gallery {...props} isLoaded={false} />)).toMatchSnapshot();
|
||||
});
|
||||
test('snapshot: loaded but no images, show empty gallery', () => {
|
||||
expect(shallow(<Gallery {...props} galleryIsEmpty />)).toMatchSnapshot();
|
||||
expect(shallowWithIntl(<Gallery {...props} galleryIsEmpty />)).toMatchSnapshot();
|
||||
});
|
||||
test('snapshot: loaded but search returns no images, show 0 search result gallery', () => {
|
||||
expect(shallow(<Gallery {...props} searchIsEmpty />)).toMatchSnapshot();
|
||||
expect(shallowWithIntl(<Gallery {...props} searchIsEmpty />)).toMatchSnapshot();
|
||||
});
|
||||
test('snapshot: loaded, show gallery', () => {
|
||||
expect(shallow(<Gallery {...props} />)).toMatchSnapshot();
|
||||
});
|
||||
test('snapshot: not shot gallery', () => {
|
||||
const wrapper = shallow(<Gallery {...props} show={false} />);
|
||||
expect(wrapper.type()).toBeNull();
|
||||
expect(shallowWithIntl(<Gallery {...props} />)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,23 +16,18 @@ export const GalleryCard = ({
|
||||
asset,
|
||||
}) => (
|
||||
<SelectableBox
|
||||
className="card bg-white"
|
||||
className="card bg-white shadow-none border-0 py-0"
|
||||
key={asset.externalUrl}
|
||||
type="radio"
|
||||
value={asset.id}
|
||||
style={{
|
||||
padding: '10px 20px',
|
||||
border: 'none',
|
||||
boxShadow: 'none',
|
||||
}}
|
||||
>
|
||||
<div className="card-div d-flex flex-row flex-nowrap">
|
||||
<div style={{
|
||||
position: 'relative',
|
||||
width: '200px',
|
||||
height: '100px',
|
||||
margin: '18px 0 0 0',
|
||||
}}
|
||||
<div className="card-div d-flex flex-row flex-nowrap align-items-center">
|
||||
<div
|
||||
className="position-relative"
|
||||
style={{
|
||||
width: '200px',
|
||||
height: '100px',
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
style={{ border: 'none', width: '200px', height: '100px' }}
|
||||
@@ -57,7 +52,7 @@ export const GalleryCard = ({
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<div className="card-text p-3" style={{ marginTop: '10px' }}>
|
||||
<div className="card-text px-3 py-2" style={{ marginTop: '10px' }}>
|
||||
<h3 className="text-primary-500">{asset.displayName}</h3>
|
||||
{ asset.transcripts && (
|
||||
<div style={{ margin: '0 0 5px 0' }}>
|
||||
@@ -86,7 +81,7 @@ GalleryCard.propTypes = {
|
||||
displayName: PropTypes.string,
|
||||
externalUrl: PropTypes.string,
|
||||
id: PropTypes.string,
|
||||
dateAdded: PropTypes.number,
|
||||
dateAdded: PropTypes.oneOfType([PropTypes.number, PropTypes.instanceOf(Date)]),
|
||||
locked: PropTypes.bool,
|
||||
portableUrl: PropTypes.string,
|
||||
thumbnail: PropTypes.string,
|
||||
@@ -94,7 +89,7 @@ GalleryCard.propTypes = {
|
||||
duration: PropTypes.number,
|
||||
status: PropTypes.string,
|
||||
statusBadgeVariant: PropTypes.string,
|
||||
transcripts: PropTypes.shape([]),
|
||||
transcripts: PropTypes.arrayOf(PropTypes.string),
|
||||
}).isRequired,
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import React from 'react';
|
||||
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { Dropdown, DropdownToggle, Form } from '@edx/paragon';
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import { filterKeys, filterMessages } from '../../containers/VideoGallery/utils';
|
||||
|
||||
const MultiSelectFilterDropdown = ({
|
||||
selected, onSelectionChange,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
return (
|
||||
<Dropdown autoClose={false}>
|
||||
<DropdownToggle variant="outline" id="gallery-filter">
|
||||
{intl.formatMessage(filterMessages.title)}
|
||||
</DropdownToggle>
|
||||
<Dropdown.Menu renderOnMount className="p-2">
|
||||
{Object.keys(filterKeys).map(key => (
|
||||
<Dropdown.Item
|
||||
key={key}
|
||||
as={Form.Checkbox}
|
||||
checked={selected.includes(key)}
|
||||
onChange={onSelectionChange(key)}
|
||||
>
|
||||
<span className="p-1">{intl.formatMessage(filterMessages[key])}</span>
|
||||
</Dropdown.Item>
|
||||
))}
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
);
|
||||
};
|
||||
|
||||
MultiSelectFilterDropdown.propTypes = {
|
||||
selected: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
onSelectionChange: PropTypes.func.isRequired,
|
||||
};
|
||||
export default MultiSelectFilterDropdown;
|
||||
@@ -2,16 +2,17 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
ActionRow, Dropdown, Form, Icon, IconButton,
|
||||
ActionRow, Form, Icon, IconButton, SelectMenu, MenuItem,
|
||||
} from '@edx/paragon';
|
||||
import { Close, Search } from '@edx/paragon/icons';
|
||||
import {
|
||||
FormattedMessage,
|
||||
injectIntl,
|
||||
intlShape,
|
||||
useIntl,
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
|
||||
import messages from './messages';
|
||||
import MultiSelectFilterDropdown from './MultiSelectFilterDropdown';
|
||||
import { sortKeys, sortMessages } from '../../containers/VideoGallery/utils';
|
||||
|
||||
export const SearchSort = ({
|
||||
searchString,
|
||||
@@ -19,28 +20,25 @@ export const SearchSort = ({
|
||||
clearSearchString,
|
||||
sortBy,
|
||||
onSortClick,
|
||||
sortKeys,
|
||||
sortMessages,
|
||||
filterBy,
|
||||
onFilterClick,
|
||||
filterKeys,
|
||||
filterMessages,
|
||||
showSwitch,
|
||||
switchMessage,
|
||||
onSwitchClick,
|
||||
// injected
|
||||
intl,
|
||||
}) => (
|
||||
<ActionRow>
|
||||
<Form.Group style={{ margin: 0 }}>
|
||||
<Form.Control
|
||||
autoFocus
|
||||
onChange={onSearchChange}
|
||||
placeholder={intl.formatMessage(messages.searchPlaceholder)}
|
||||
trailingElement={
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
return (
|
||||
<ActionRow>
|
||||
<Form.Group style={{ margin: 0 }}>
|
||||
<Form.Control
|
||||
autoFocus
|
||||
onChange={onSearchChange}
|
||||
placeholder={intl.formatMessage(messages.searchPlaceholder)}
|
||||
trailingElement={
|
||||
searchString
|
||||
? (
|
||||
<IconButton
|
||||
alt={intl.formatMessage(messages.clearSearch)}
|
||||
iconAs={Icon}
|
||||
invertColors
|
||||
isActive
|
||||
@@ -51,62 +49,43 @@ export const SearchSort = ({
|
||||
)
|
||||
: <Icon src={Search} />
|
||||
}
|
||||
value={searchString}
|
||||
/>
|
||||
</Form.Group>
|
||||
value={searchString}
|
||||
/>
|
||||
</Form.Group>
|
||||
|
||||
{ !showSwitch && <ActionRow.Spacer /> }
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle className="text-gray-700" id="gallery-sort-button" variant="tertiary">
|
||||
<FormattedMessage {...sortMessages[sortBy]} />
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
{ !showSwitch && <ActionRow.Spacer /> }
|
||||
<SelectMenu variant="link">
|
||||
{Object.keys(sortKeys).map(key => (
|
||||
<Dropdown.Item key={key} onClick={onSortClick(key)}>
|
||||
<MenuItem key={key} onClick={onSortClick(key)} defaultSelected={key === sortBy}>
|
||||
<FormattedMessage {...sortMessages[key]} />
|
||||
</Dropdown.Item>
|
||||
</MenuItem>
|
||||
))}
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
</SelectMenu>
|
||||
|
||||
{ filterKeys && filterMessages && (
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle className="text-gray-700" id="gallery-filter-button" variant="tertiary">
|
||||
<FormattedMessage {...filterMessages[filterBy]} />
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
{Object.keys(filterKeys).map(key => (
|
||||
<Dropdown.Item key={key} onClick={onFilterClick(key)}>
|
||||
<FormattedMessage {...filterMessages[key]} />
|
||||
</Dropdown.Item>
|
||||
))}
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
)}
|
||||
{onFilterClick && <MultiSelectFilterDropdown selected={filterBy} onSelectionChange={onFilterClick} />}
|
||||
|
||||
{ showSwitch && (
|
||||
<>
|
||||
<ActionRow.Spacer />
|
||||
<Form.SwitchSet
|
||||
name="switch"
|
||||
onChange={onSwitchClick}
|
||||
isInline
|
||||
>
|
||||
<Form.Switch className="text-gray-700" value="switch-value" floatLabelLeft>
|
||||
<FormattedMessage {...switchMessage} />
|
||||
</Form.Switch>
|
||||
</Form.SwitchSet>
|
||||
</>
|
||||
)}
|
||||
{ showSwitch && (
|
||||
<>
|
||||
<ActionRow.Spacer />
|
||||
<Form.SwitchSet
|
||||
name="switch"
|
||||
onChange={onSwitchClick}
|
||||
isInline
|
||||
>
|
||||
<Form.Switch className="text-gray-700" value="switch-value" floatLabelLeft>
|
||||
<FormattedMessage {...switchMessage} />
|
||||
</Form.Switch>
|
||||
</Form.SwitchSet>
|
||||
</>
|
||||
)}
|
||||
|
||||
</ActionRow>
|
||||
);
|
||||
</ActionRow>
|
||||
);
|
||||
};
|
||||
|
||||
SearchSort.defaultProps = {
|
||||
filterBy: '',
|
||||
onFilterClick: null,
|
||||
filterKeys: null,
|
||||
filterMessages: null,
|
||||
showSwitch: false,
|
||||
onSwitchClick: null,
|
||||
};
|
||||
@@ -117,17 +96,11 @@ SearchSort.propTypes = {
|
||||
clearSearchString: PropTypes.func.isRequired,
|
||||
sortBy: PropTypes.string.isRequired,
|
||||
onSortClick: PropTypes.func.isRequired,
|
||||
sortKeys: PropTypes.shape({}).isRequired,
|
||||
sortMessages: PropTypes.shape({}).isRequired,
|
||||
filterBy: PropTypes.string,
|
||||
filterBy: PropTypes.arrayOf(PropTypes.string),
|
||||
onFilterClick: PropTypes.func,
|
||||
filterKeys: PropTypes.shape({}),
|
||||
filterMessages: PropTypes.shape({}),
|
||||
showSwitch: PropTypes.bool,
|
||||
switchMessage: PropTypes.shape({}).isRequired,
|
||||
onSwitchClick: PropTypes.func,
|
||||
// injected
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(SearchSort);
|
||||
export default SearchSort;
|
||||
|
||||
@@ -1,101 +1,89 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { Dropdown } from '@edx/paragon';
|
||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { formatMessage } from '../../../testUtils';
|
||||
import '@testing-library/jest-dom';
|
||||
import {
|
||||
act, fireEvent, render, screen,
|
||||
} from '@testing-library/react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { sortKeys, sortMessages } from '../ImageUploadModal/SelectImageModal/utils';
|
||||
import { filterKeys, filterMessages } from '../../containers/VideoGallery/utils';
|
||||
import { filterMessages } from '../../containers/VideoGallery/utils';
|
||||
import { SearchSort } from './SearchSort';
|
||||
import messages from './messages';
|
||||
|
||||
jest.unmock('react-redux');
|
||||
jest.unmock('@edx/frontend-platform/i18n');
|
||||
jest.unmock('@edx/paragon');
|
||||
jest.unmock('@edx/paragon/icons');
|
||||
|
||||
describe('SearchSort component', () => {
|
||||
describe('snapshots without filterKeys', () => {
|
||||
const props = {
|
||||
searchString: 'props.searchString',
|
||||
onSearchChange: jest.fn().mockName('props.onSearchChange'),
|
||||
clearSearchString: jest.fn().mockName('props.clearSearchString'),
|
||||
sortBy: sortKeys.dateOldest,
|
||||
sortKeys,
|
||||
sortMessages,
|
||||
onSortClick: jest.fn().mockName('props.onSortClick'),
|
||||
intl: { formatMessage },
|
||||
};
|
||||
test('with search string (close button)', () => {
|
||||
expect(shallow(<SearchSort {...props} />)).toMatchSnapshot();
|
||||
});
|
||||
test('without search string (search icon)', () => {
|
||||
expect(shallow(<SearchSort {...props} searchString="" />)).toMatchSnapshot();
|
||||
});
|
||||
test('adds a sort option for each sortKey', () => {
|
||||
const el = shallow(<SearchSort {...props} />);
|
||||
expect(el.find(Dropdown).containsMatchingElement(
|
||||
<FormattedMessage {...sortMessages.dateNewest} />,
|
||||
)).toEqual(true);
|
||||
expect(el.find(Dropdown).containsMatchingElement(
|
||||
<FormattedMessage {...sortMessages.dateOldest} />,
|
||||
)).toEqual(true);
|
||||
expect(el.find(Dropdown).containsMatchingElement(
|
||||
<FormattedMessage {...sortMessages.nameAscending} />,
|
||||
)).toEqual(true);
|
||||
expect(el.find(Dropdown).containsMatchingElement(
|
||||
<FormattedMessage {...sortMessages.nameDescending} />,
|
||||
)).toEqual(true);
|
||||
const props = {
|
||||
searchString: '',
|
||||
onSearchChange: jest.fn()
|
||||
.mockName('props.onSearchChange'),
|
||||
clearSearchString: jest.fn()
|
||||
.mockName('props.clearSearchString'),
|
||||
sortBy: sortKeys.dateOldest,
|
||||
sortKeys,
|
||||
sortMessages,
|
||||
onSortClick: jest.fn()
|
||||
.mockName('props.onSortClick'),
|
||||
switchMessage: {
|
||||
id: 'test.id',
|
||||
defaultMessage: 'test message',
|
||||
},
|
||||
onFilterClick: jest.fn(),
|
||||
showSwitch: true,
|
||||
};
|
||||
|
||||
function getComponent(overrideProps = {}) {
|
||||
return render(
|
||||
<IntlProvider locale="en">
|
||||
<SearchSort {...props} {...overrideProps} />
|
||||
</IntlProvider>,
|
||||
);
|
||||
}
|
||||
|
||||
test('adds a sort option for each sortKey', async () => {
|
||||
const { getByRole } = getComponent();
|
||||
await act(() => {
|
||||
fireEvent.click(screen.getByRole('button', {
|
||||
name: /by date added \(oldest\)/i,
|
||||
}));
|
||||
});
|
||||
Object.values(sortMessages)
|
||||
.forEach(({ defaultMessage }) => {
|
||||
expect(getByRole('link', { name: defaultMessage }))
|
||||
.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
describe('snapshots with filterKeys', () => {
|
||||
const props = {
|
||||
searchString: 'props.searchString',
|
||||
onSearchChange: jest.fn().mockName('props.onSearchChange'),
|
||||
clearSearchString: jest.fn().mockName('props.clearSearchString'),
|
||||
sortBy: sortKeys.dateOldest,
|
||||
sortKeys,
|
||||
sortMessages,
|
||||
filterKeys,
|
||||
filterMessages,
|
||||
showSwitch: true,
|
||||
onSortClick: jest.fn().mockName('props.onSortClick'),
|
||||
onFilterClick: jest.fn().mockName('props.onFilterClick'),
|
||||
intl: { formatMessage },
|
||||
};
|
||||
test('with search string (close button)', () => {
|
||||
expect(shallow(<SearchSort {...props} />)).toMatchSnapshot();
|
||||
test('adds a sort option for each sortKey', async () => {
|
||||
const { getByRole } = getComponent();
|
||||
await act(() => {
|
||||
fireEvent.click(screen.getByRole('button', { name: /by date added \(oldest\)/i }));
|
||||
});
|
||||
test('without search string (search icon)', () => {
|
||||
expect(shallow(<SearchSort {...props} searchString="" />)).toMatchSnapshot();
|
||||
});
|
||||
test('adds a sort option for each sortKey', () => {
|
||||
const el = shallow(<SearchSort {...props} />);
|
||||
expect(el.find(Dropdown).containsMatchingElement(
|
||||
<FormattedMessage {...sortMessages.dateNewest} />,
|
||||
)).toEqual(true);
|
||||
expect(el.find(Dropdown).containsMatchingElement(
|
||||
<FormattedMessage {...sortMessages.dateOldest} />,
|
||||
)).toEqual(true);
|
||||
expect(el.find(Dropdown).containsMatchingElement(
|
||||
<FormattedMessage {...sortMessages.nameAscending} />,
|
||||
)).toEqual(true);
|
||||
expect(el.find(Dropdown).containsMatchingElement(
|
||||
<FormattedMessage {...sortMessages.nameDescending} />,
|
||||
)).toEqual(true);
|
||||
});
|
||||
test('adds a filter option for each filterKet', () => {
|
||||
const el = shallow(<SearchSort {...props} />);
|
||||
expect(el.find(Dropdown).containsMatchingElement(
|
||||
<FormattedMessage {...filterMessages.videoStatus} />,
|
||||
)).toEqual(true);
|
||||
expect(el.find(Dropdown).containsMatchingElement(
|
||||
<FormattedMessage {...filterMessages.uploading} />,
|
||||
)).toEqual(true);
|
||||
expect(el.find(Dropdown).containsMatchingElement(
|
||||
<FormattedMessage {...filterMessages.processing} />,
|
||||
)).toEqual(true);
|
||||
expect(el.find(Dropdown).containsMatchingElement(
|
||||
<FormattedMessage {...filterMessages.ready} />,
|
||||
)).toEqual(true);
|
||||
expect(el.find(Dropdown).containsMatchingElement(
|
||||
<FormattedMessage {...filterMessages.failed} />,
|
||||
)).toEqual(true);
|
||||
Object.values(sortMessages)
|
||||
.forEach(({ defaultMessage }) => {
|
||||
expect(getByRole('link', { name: defaultMessage }))
|
||||
.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
test('adds a filter option for each filterKet', async () => {
|
||||
const { getByRole } = getComponent();
|
||||
await act(() => {
|
||||
fireEvent.click(screen.getByRole('button', { name: /video status/i }));
|
||||
});
|
||||
Object.keys(filterMessages)
|
||||
.forEach((key) => {
|
||||
if (key !== 'title') {
|
||||
expect(getByRole('checkbox', { name: filterMessages[key].defaultMessage }))
|
||||
.toBeInTheDocument();
|
||||
}
|
||||
});
|
||||
});
|
||||
test('searchbox should show clear message button when not empty', async () => {
|
||||
const { queryByRole } = getComponent({ searchString: 'some string' });
|
||||
expect(queryByRole('button', { name: messages.clearSearch.defaultMessage }))
|
||||
.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,104 +1,297 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`TextEditor Image Gallery component component snapshot: loaded but no images, show empty gallery 1`] = `
|
||||
<div
|
||||
className="gallery p-4 bg-light-400"
|
||||
style={
|
||||
<ContextProvider
|
||||
value={
|
||||
Object {
|
||||
"height": "375px",
|
||||
"margin": "0 -1.5rem",
|
||||
"$t": [Function],
|
||||
"defaultFormats": Object {},
|
||||
"defaultLocale": "en",
|
||||
"defaultRichTextElements": undefined,
|
||||
"fallbackOnEmptyString": true,
|
||||
"formatDate": [Function],
|
||||
"formatDateTimeRange": [Function],
|
||||
"formatDateToParts": [Function],
|
||||
"formatDisplayName": [Function],
|
||||
"formatList": [Function],
|
||||
"formatListToParts": [Function],
|
||||
"formatMessage": [Function],
|
||||
"formatNumber": [Function],
|
||||
"formatNumberToParts": [Function],
|
||||
"formatPlural": [Function],
|
||||
"formatRelativeTime": [Function],
|
||||
"formatTime": [Function],
|
||||
"formatTimeToParts": [Function],
|
||||
"formats": Object {},
|
||||
"formatters": Object {
|
||||
"getDateTimeFormat": [Function],
|
||||
"getDisplayNames": [Function],
|
||||
"getListFormat": [Function],
|
||||
"getMessageFormat": [Function],
|
||||
"getNumberFormat": [Function],
|
||||
"getPluralRules": [Function],
|
||||
"getRelativeTimeFormat": [Function],
|
||||
},
|
||||
"locale": "en",
|
||||
"messages": Object {},
|
||||
"onError": [Function],
|
||||
"onWarn": [Function],
|
||||
"textComponent": Symbol(react.fragment),
|
||||
"timeZone": undefined,
|
||||
"wrapRichTextChunksInFragment": undefined,
|
||||
}
|
||||
}
|
||||
>
|
||||
<FormattedMessage />
|
||||
</div>
|
||||
<Gallery
|
||||
displayList={
|
||||
Array [
|
||||
Object {
|
||||
"id": 1,
|
||||
},
|
||||
Object {
|
||||
"id": 2,
|
||||
},
|
||||
Object {
|
||||
"id": 3,
|
||||
},
|
||||
]
|
||||
}
|
||||
emptyGalleryLabel={
|
||||
Object {
|
||||
"defaultMessage": "Empty Gallery",
|
||||
"id": "emptyGalleryMsg",
|
||||
}
|
||||
}
|
||||
galleryIsEmpty={true}
|
||||
height="375px"
|
||||
highlighted="props.highlighted"
|
||||
isLoaded={true}
|
||||
onHighlightChange={[MockFunction props.onHighlightChange]}
|
||||
searchIsEmpty={false}
|
||||
show={true}
|
||||
showIdsOnCards={false}
|
||||
/>
|
||||
</ContextProvider>
|
||||
`;
|
||||
|
||||
exports[`TextEditor Image Gallery component component snapshot: loaded but search returns no images, show 0 search result gallery 1`] = `
|
||||
<div
|
||||
className="gallery p-4 bg-light-400"
|
||||
style={
|
||||
<ContextProvider
|
||||
value={
|
||||
Object {
|
||||
"height": "375px",
|
||||
"margin": "0 -1.5rem",
|
||||
"$t": [Function],
|
||||
"defaultFormats": Object {},
|
||||
"defaultLocale": "en",
|
||||
"defaultRichTextElements": undefined,
|
||||
"fallbackOnEmptyString": true,
|
||||
"formatDate": [Function],
|
||||
"formatDateTimeRange": [Function],
|
||||
"formatDateToParts": [Function],
|
||||
"formatDisplayName": [Function],
|
||||
"formatList": [Function],
|
||||
"formatListToParts": [Function],
|
||||
"formatMessage": [Function],
|
||||
"formatNumber": [Function],
|
||||
"formatNumberToParts": [Function],
|
||||
"formatPlural": [Function],
|
||||
"formatRelativeTime": [Function],
|
||||
"formatTime": [Function],
|
||||
"formatTimeToParts": [Function],
|
||||
"formats": Object {},
|
||||
"formatters": Object {
|
||||
"getDateTimeFormat": [Function],
|
||||
"getDisplayNames": [Function],
|
||||
"getListFormat": [Function],
|
||||
"getMessageFormat": [Function],
|
||||
"getNumberFormat": [Function],
|
||||
"getPluralRules": [Function],
|
||||
"getRelativeTimeFormat": [Function],
|
||||
},
|
||||
"locale": "en",
|
||||
"messages": Object {},
|
||||
"onError": [Function],
|
||||
"onWarn": [Function],
|
||||
"textComponent": Symbol(react.fragment),
|
||||
"timeZone": undefined,
|
||||
"wrapRichTextChunksInFragment": undefined,
|
||||
}
|
||||
}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="No search results."
|
||||
description="Label for when search returns nothing."
|
||||
id="authoring.selectionmodal.emptySearchLabel"
|
||||
<Gallery
|
||||
displayList={
|
||||
Array [
|
||||
Object {
|
||||
"id": 1,
|
||||
},
|
||||
Object {
|
||||
"id": 2,
|
||||
},
|
||||
Object {
|
||||
"id": 3,
|
||||
},
|
||||
]
|
||||
}
|
||||
emptyGalleryLabel={
|
||||
Object {
|
||||
"defaultMessage": "Empty Gallery",
|
||||
"id": "emptyGalleryMsg",
|
||||
}
|
||||
}
|
||||
galleryIsEmpty={false}
|
||||
height="375px"
|
||||
highlighted="props.highlighted"
|
||||
isLoaded={true}
|
||||
onHighlightChange={[MockFunction props.onHighlightChange]}
|
||||
searchIsEmpty={true}
|
||||
show={true}
|
||||
showIdsOnCards={false}
|
||||
/>
|
||||
</div>
|
||||
</ContextProvider>
|
||||
`;
|
||||
|
||||
exports[`TextEditor Image Gallery component component snapshot: loaded, show gallery 1`] = `
|
||||
<Scrollable
|
||||
className="gallery bg-light-400"
|
||||
style={
|
||||
<ContextProvider
|
||||
value={
|
||||
Object {
|
||||
"height": "375px",
|
||||
"margin": "0 -1.5rem",
|
||||
"$t": [Function],
|
||||
"defaultFormats": Object {},
|
||||
"defaultLocale": "en",
|
||||
"defaultRichTextElements": undefined,
|
||||
"fallbackOnEmptyString": true,
|
||||
"formatDate": [Function],
|
||||
"formatDateTimeRange": [Function],
|
||||
"formatDateToParts": [Function],
|
||||
"formatDisplayName": [Function],
|
||||
"formatList": [Function],
|
||||
"formatListToParts": [Function],
|
||||
"formatMessage": [Function],
|
||||
"formatNumber": [Function],
|
||||
"formatNumberToParts": [Function],
|
||||
"formatPlural": [Function],
|
||||
"formatRelativeTime": [Function],
|
||||
"formatTime": [Function],
|
||||
"formatTimeToParts": [Function],
|
||||
"formats": Object {},
|
||||
"formatters": Object {
|
||||
"getDateTimeFormat": [Function],
|
||||
"getDisplayNames": [Function],
|
||||
"getListFormat": [Function],
|
||||
"getMessageFormat": [Function],
|
||||
"getNumberFormat": [Function],
|
||||
"getPluralRules": [Function],
|
||||
"getRelativeTimeFormat": [Function],
|
||||
},
|
||||
"locale": "en",
|
||||
"messages": Object {},
|
||||
"onError": [Function],
|
||||
"onWarn": [Function],
|
||||
"textComponent": Symbol(react.fragment),
|
||||
"timeZone": undefined,
|
||||
"wrapRichTextChunksInFragment": undefined,
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="p-4"
|
||||
>
|
||||
<SelectableBox.Set
|
||||
columns={1}
|
||||
name="images"
|
||||
onChange={[MockFunction props.onHighlightChange]}
|
||||
type="radio"
|
||||
value="props.highlighted"
|
||||
>
|
||||
<GalleryCard
|
||||
asset={
|
||||
Object {
|
||||
"id": 1,
|
||||
}
|
||||
}
|
||||
key="1"
|
||||
showId={false}
|
||||
/>
|
||||
<GalleryCard
|
||||
asset={
|
||||
Object {
|
||||
"id": 2,
|
||||
}
|
||||
}
|
||||
key="2"
|
||||
showId={false}
|
||||
/>
|
||||
<GalleryCard
|
||||
asset={
|
||||
Object {
|
||||
"id": 3,
|
||||
}
|
||||
}
|
||||
key="3"
|
||||
showId={false}
|
||||
/>
|
||||
</SelectableBox.Set>
|
||||
</div>
|
||||
</Scrollable>
|
||||
<Gallery
|
||||
displayList={
|
||||
Array [
|
||||
Object {
|
||||
"id": 1,
|
||||
},
|
||||
Object {
|
||||
"id": 2,
|
||||
},
|
||||
Object {
|
||||
"id": 3,
|
||||
},
|
||||
]
|
||||
}
|
||||
emptyGalleryLabel={
|
||||
Object {
|
||||
"defaultMessage": "Empty Gallery",
|
||||
"id": "emptyGalleryMsg",
|
||||
}
|
||||
}
|
||||
galleryIsEmpty={false}
|
||||
height="375px"
|
||||
highlighted="props.highlighted"
|
||||
isLoaded={true}
|
||||
onHighlightChange={[MockFunction props.onHighlightChange]}
|
||||
searchIsEmpty={false}
|
||||
show={true}
|
||||
showIdsOnCards={false}
|
||||
/>
|
||||
</ContextProvider>
|
||||
`;
|
||||
|
||||
exports[`TextEditor Image Gallery component component snapshot: not loaded, show spinner 1`] = `
|
||||
<div
|
||||
style={
|
||||
<ContextProvider
|
||||
value={
|
||||
Object {
|
||||
"left": "50%",
|
||||
"position": "absolute",
|
||||
"top": "50%",
|
||||
"transform": "translate(-50%, -50%)",
|
||||
"$t": [Function],
|
||||
"defaultFormats": Object {},
|
||||
"defaultLocale": "en",
|
||||
"defaultRichTextElements": undefined,
|
||||
"fallbackOnEmptyString": true,
|
||||
"formatDate": [Function],
|
||||
"formatDateTimeRange": [Function],
|
||||
"formatDateToParts": [Function],
|
||||
"formatDisplayName": [Function],
|
||||
"formatList": [Function],
|
||||
"formatListToParts": [Function],
|
||||
"formatMessage": [Function],
|
||||
"formatNumber": [Function],
|
||||
"formatNumberToParts": [Function],
|
||||
"formatPlural": [Function],
|
||||
"formatRelativeTime": [Function],
|
||||
"formatTime": [Function],
|
||||
"formatTimeToParts": [Function],
|
||||
"formats": Object {},
|
||||
"formatters": Object {
|
||||
"getDateTimeFormat": [Function],
|
||||
"getDisplayNames": [Function],
|
||||
"getListFormat": [Function],
|
||||
"getMessageFormat": [Function],
|
||||
"getNumberFormat": [Function],
|
||||
"getPluralRules": [Function],
|
||||
"getRelativeTimeFormat": [Function],
|
||||
},
|
||||
"locale": "en",
|
||||
"messages": Object {},
|
||||
"onError": [Function],
|
||||
"onWarn": [Function],
|
||||
"textComponent": Symbol(react.fragment),
|
||||
"timeZone": undefined,
|
||||
"wrapRichTextChunksInFragment": undefined,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Spinner
|
||||
animation="border"
|
||||
className="mie-3"
|
||||
screenReaderText="loading..."
|
||||
<Gallery
|
||||
displayList={
|
||||
Array [
|
||||
Object {
|
||||
"id": 1,
|
||||
},
|
||||
Object {
|
||||
"id": 2,
|
||||
},
|
||||
Object {
|
||||
"id": 3,
|
||||
},
|
||||
]
|
||||
}
|
||||
emptyGalleryLabel={
|
||||
Object {
|
||||
"defaultMessage": "Empty Gallery",
|
||||
"id": "emptyGalleryMsg",
|
||||
}
|
||||
}
|
||||
galleryIsEmpty={false}
|
||||
height="375px"
|
||||
highlighted="props.highlighted"
|
||||
isLoaded={false}
|
||||
onHighlightChange={[MockFunction props.onHighlightChange]}
|
||||
searchIsEmpty={false}
|
||||
show={true}
|
||||
showIdsOnCards={false}
|
||||
/>
|
||||
</div>
|
||||
</ContextProvider>
|
||||
`;
|
||||
|
||||
@@ -2,26 +2,18 @@
|
||||
|
||||
exports[`GalleryCard component snapshot with duration badge 1`] = `
|
||||
<SelectableBox
|
||||
className="card bg-white"
|
||||
className="card bg-white shadow-none border-0 py-0"
|
||||
key="props.img.externalUrl"
|
||||
style={
|
||||
Object {
|
||||
"border": "none",
|
||||
"boxShadow": "none",
|
||||
"padding": "10px 20px",
|
||||
}
|
||||
}
|
||||
type="radio"
|
||||
>
|
||||
<div
|
||||
className="card-div d-flex flex-row flex-nowrap"
|
||||
className="card-div d-flex flex-row flex-nowrap align-items-center"
|
||||
>
|
||||
<div
|
||||
className="position-relative"
|
||||
style={
|
||||
Object {
|
||||
"height": "100px",
|
||||
"margin": "18px 0 0 0",
|
||||
"position": "relative",
|
||||
"width": "200px",
|
||||
}
|
||||
}
|
||||
@@ -51,7 +43,7 @@ exports[`GalleryCard component snapshot with duration badge 1`] = `
|
||||
</Component>
|
||||
</div>
|
||||
<div
|
||||
className="card-text p-3"
|
||||
className="card-text px-3 py-2"
|
||||
style={
|
||||
Object {
|
||||
"marginTop": "10px",
|
||||
@@ -94,26 +86,18 @@ exports[`GalleryCard component snapshot with duration badge 1`] = `
|
||||
|
||||
exports[`GalleryCard component snapshot with duration transcripts 1`] = `
|
||||
<SelectableBox
|
||||
className="card bg-white"
|
||||
className="card bg-white shadow-none border-0 py-0"
|
||||
key="props.img.externalUrl"
|
||||
style={
|
||||
Object {
|
||||
"border": "none",
|
||||
"boxShadow": "none",
|
||||
"padding": "10px 20px",
|
||||
}
|
||||
}
|
||||
type="radio"
|
||||
>
|
||||
<div
|
||||
className="card-div d-flex flex-row flex-nowrap"
|
||||
className="card-div d-flex flex-row flex-nowrap align-items-center"
|
||||
>
|
||||
<div
|
||||
className="position-relative"
|
||||
style={
|
||||
Object {
|
||||
"height": "100px",
|
||||
"margin": "18px 0 0 0",
|
||||
"position": "relative",
|
||||
"width": "200px",
|
||||
}
|
||||
}
|
||||
@@ -130,7 +114,7 @@ exports[`GalleryCard component snapshot with duration transcripts 1`] = `
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="card-text p-3"
|
||||
className="card-text px-3 py-2"
|
||||
style={
|
||||
Object {
|
||||
"marginTop": "10px",
|
||||
@@ -188,26 +172,18 @@ exports[`GalleryCard component snapshot with duration transcripts 1`] = `
|
||||
|
||||
exports[`GalleryCard component snapshot with status badge 1`] = `
|
||||
<SelectableBox
|
||||
className="card bg-white"
|
||||
className="card bg-white shadow-none border-0 py-0"
|
||||
key="props.img.externalUrl"
|
||||
style={
|
||||
Object {
|
||||
"border": "none",
|
||||
"boxShadow": "none",
|
||||
"padding": "10px 20px",
|
||||
}
|
||||
}
|
||||
type="radio"
|
||||
>
|
||||
<div
|
||||
className="card-div d-flex flex-row flex-nowrap"
|
||||
className="card-div d-flex flex-row flex-nowrap align-items-center"
|
||||
>
|
||||
<div
|
||||
className="position-relative"
|
||||
style={
|
||||
Object {
|
||||
"height": "100px",
|
||||
"margin": "18px 0 0 0",
|
||||
"position": "relative",
|
||||
"width": "200px",
|
||||
}
|
||||
}
|
||||
@@ -236,7 +212,7 @@ exports[`GalleryCard component snapshot with status badge 1`] = `
|
||||
</Component>
|
||||
</div>
|
||||
<div
|
||||
className="card-text p-3"
|
||||
className="card-text px-3 py-2"
|
||||
style={
|
||||
Object {
|
||||
"marginTop": "10px",
|
||||
@@ -279,26 +255,18 @@ exports[`GalleryCard component snapshot with status badge 1`] = `
|
||||
|
||||
exports[`GalleryCard component snapshot: dateAdded=12345 1`] = `
|
||||
<SelectableBox
|
||||
className="card bg-white"
|
||||
className="card bg-white shadow-none border-0 py-0"
|
||||
key="props.img.externalUrl"
|
||||
style={
|
||||
Object {
|
||||
"border": "none",
|
||||
"boxShadow": "none",
|
||||
"padding": "10px 20px",
|
||||
}
|
||||
}
|
||||
type="radio"
|
||||
>
|
||||
<div
|
||||
className="card-div d-flex flex-row flex-nowrap"
|
||||
className="card-div d-flex flex-row flex-nowrap align-items-center"
|
||||
>
|
||||
<div
|
||||
className="position-relative"
|
||||
style={
|
||||
Object {
|
||||
"height": "100px",
|
||||
"margin": "18px 0 0 0",
|
||||
"position": "relative",
|
||||
"width": "200px",
|
||||
}
|
||||
}
|
||||
@@ -315,7 +283,7 @@ exports[`GalleryCard component snapshot: dateAdded=12345 1`] = `
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="card-text p-3"
|
||||
className="card-text px-3 py-2"
|
||||
style={
|
||||
Object {
|
||||
"marginTop": "10px",
|
||||
|
||||
@@ -1,445 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`SearchSort component snapshots with filterKeys with search string (close button) 1`] = `
|
||||
<ActionRow>
|
||||
<Form.Group
|
||||
style={
|
||||
Object {
|
||||
"margin": 0,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Form.Control
|
||||
autoFocus={true}
|
||||
onChange={[MockFunction props.onSearchChange]}
|
||||
placeholder="Search"
|
||||
trailingElement={
|
||||
<IconButton
|
||||
iconAs="Icon"
|
||||
invertColors={true}
|
||||
isActive={true}
|
||||
onClick={[MockFunction props.clearSearchString]}
|
||||
size="sm"
|
||||
src={[MockFunction icons.Close]}
|
||||
/>
|
||||
}
|
||||
value="props.searchString"
|
||||
/>
|
||||
</Form.Group>
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
className="text-gray-700"
|
||||
id="gallery-sort-button"
|
||||
variant="tertiary"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By date added (oldest)"
|
||||
description="Dropdown label for sorting by date (oldest)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.dateoldest.label"
|
||||
/>
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
<Dropdown.Item
|
||||
key="dateNewest"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By date added (newest)"
|
||||
description="Dropdown label for sorting by date (newest)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.datenewest.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="dateOldest"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By date added (oldest)"
|
||||
description="Dropdown label for sorting by date (oldest)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.dateoldest.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="nameAscending"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By name (ascending)"
|
||||
description="Dropdown label for sorting by name (ascending)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.nameascending.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="nameDescending"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By name (descending)"
|
||||
description="Dropdown label for sorting by name (descending)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.namedescending.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
className="text-gray-700"
|
||||
id="gallery-filter-button"
|
||||
variant="tertiary"
|
||||
>
|
||||
<FormattedMessage />
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
<Dropdown.Item
|
||||
key="videoStatus"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Video status"
|
||||
description="Dropdown label for filter by video status (none)"
|
||||
id="authoring.selectvideomodal.filter.videostatusnone.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="uploading"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Uploading"
|
||||
description="Dropdown label for filter by video status (uploading)"
|
||||
id="authoring.selectvideomodal.filter.videostatusuploading.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="processing"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Processing"
|
||||
description="Dropdown label for filter by video status (processing)"
|
||||
id="authoring.selectvideomodal.filter.videostatusprocessing.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="ready"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Ready"
|
||||
description="Dropdown label for filter by video status (ready)"
|
||||
id="authoring.selectvideomodal.filter.videostatusready.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="failed"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Failed"
|
||||
description="Dropdown label for filter by video status (failed)"
|
||||
id="authoring.selectvideomodal.filter.videostatusfailed.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
<ActionRow.Spacer />
|
||||
<Component
|
||||
isInline={true}
|
||||
name="switch"
|
||||
onChange={null}
|
||||
>
|
||||
<Component
|
||||
className="text-gray-700"
|
||||
floatLabelLeft={true}
|
||||
value="switch-value"
|
||||
>
|
||||
<FormattedMessage />
|
||||
</Component>
|
||||
</Component>
|
||||
</ActionRow>
|
||||
`;
|
||||
|
||||
exports[`SearchSort component snapshots with filterKeys without search string (search icon) 1`] = `
|
||||
<ActionRow>
|
||||
<Form.Group
|
||||
style={
|
||||
Object {
|
||||
"margin": 0,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Form.Control
|
||||
autoFocus={true}
|
||||
onChange={[MockFunction props.onSearchChange]}
|
||||
placeholder="Search"
|
||||
trailingElement={<Icon />}
|
||||
value=""
|
||||
/>
|
||||
</Form.Group>
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
className="text-gray-700"
|
||||
id="gallery-sort-button"
|
||||
variant="tertiary"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By date added (oldest)"
|
||||
description="Dropdown label for sorting by date (oldest)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.dateoldest.label"
|
||||
/>
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
<Dropdown.Item
|
||||
key="dateNewest"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By date added (newest)"
|
||||
description="Dropdown label for sorting by date (newest)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.datenewest.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="dateOldest"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By date added (oldest)"
|
||||
description="Dropdown label for sorting by date (oldest)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.dateoldest.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="nameAscending"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By name (ascending)"
|
||||
description="Dropdown label for sorting by name (ascending)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.nameascending.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="nameDescending"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By name (descending)"
|
||||
description="Dropdown label for sorting by name (descending)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.namedescending.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
className="text-gray-700"
|
||||
id="gallery-filter-button"
|
||||
variant="tertiary"
|
||||
>
|
||||
<FormattedMessage />
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
<Dropdown.Item
|
||||
key="videoStatus"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Video status"
|
||||
description="Dropdown label for filter by video status (none)"
|
||||
id="authoring.selectvideomodal.filter.videostatusnone.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="uploading"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Uploading"
|
||||
description="Dropdown label for filter by video status (uploading)"
|
||||
id="authoring.selectvideomodal.filter.videostatusuploading.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="processing"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Processing"
|
||||
description="Dropdown label for filter by video status (processing)"
|
||||
id="authoring.selectvideomodal.filter.videostatusprocessing.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="ready"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Ready"
|
||||
description="Dropdown label for filter by video status (ready)"
|
||||
id="authoring.selectvideomodal.filter.videostatusready.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="failed"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Failed"
|
||||
description="Dropdown label for filter by video status (failed)"
|
||||
id="authoring.selectvideomodal.filter.videostatusfailed.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
<ActionRow.Spacer />
|
||||
<Component
|
||||
isInline={true}
|
||||
name="switch"
|
||||
onChange={null}
|
||||
>
|
||||
<Component
|
||||
className="text-gray-700"
|
||||
floatLabelLeft={true}
|
||||
value="switch-value"
|
||||
>
|
||||
<FormattedMessage />
|
||||
</Component>
|
||||
</Component>
|
||||
</ActionRow>
|
||||
`;
|
||||
|
||||
exports[`SearchSort component snapshots without filterKeys with search string (close button) 1`] = `
|
||||
<ActionRow>
|
||||
<Form.Group
|
||||
style={
|
||||
Object {
|
||||
"margin": 0,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Form.Control
|
||||
autoFocus={true}
|
||||
onChange={[MockFunction props.onSearchChange]}
|
||||
placeholder="Search"
|
||||
trailingElement={
|
||||
<IconButton
|
||||
iconAs="Icon"
|
||||
invertColors={true}
|
||||
isActive={true}
|
||||
onClick={[MockFunction props.clearSearchString]}
|
||||
size="sm"
|
||||
src={[MockFunction icons.Close]}
|
||||
/>
|
||||
}
|
||||
value="props.searchString"
|
||||
/>
|
||||
</Form.Group>
|
||||
<ActionRow.Spacer />
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
className="text-gray-700"
|
||||
id="gallery-sort-button"
|
||||
variant="tertiary"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By date added (oldest)"
|
||||
description="Dropdown label for sorting by date (oldest)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.dateoldest.label"
|
||||
/>
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
<Dropdown.Item
|
||||
key="dateNewest"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By date added (newest)"
|
||||
description="Dropdown label for sorting by date (newest)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.datenewest.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="dateOldest"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By date added (oldest)"
|
||||
description="Dropdown label for sorting by date (oldest)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.dateoldest.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="nameAscending"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By name (ascending)"
|
||||
description="Dropdown label for sorting by name (ascending)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.nameascending.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="nameDescending"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By name (descending)"
|
||||
description="Dropdown label for sorting by name (descending)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.namedescending.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
</ActionRow>
|
||||
`;
|
||||
|
||||
exports[`SearchSort component snapshots without filterKeys without search string (search icon) 1`] = `
|
||||
<ActionRow>
|
||||
<Form.Group
|
||||
style={
|
||||
Object {
|
||||
"margin": 0,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Form.Control
|
||||
autoFocus={true}
|
||||
onChange={[MockFunction props.onSearchChange]}
|
||||
placeholder="Search"
|
||||
trailingElement={<Icon />}
|
||||
value=""
|
||||
/>
|
||||
</Form.Group>
|
||||
<ActionRow.Spacer />
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
className="text-gray-700"
|
||||
id="gallery-sort-button"
|
||||
variant="tertiary"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By date added (oldest)"
|
||||
description="Dropdown label for sorting by date (oldest)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.dateoldest.label"
|
||||
/>
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
<Dropdown.Item
|
||||
key="dateNewest"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By date added (newest)"
|
||||
description="Dropdown label for sorting by date (newest)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.datenewest.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="dateOldest"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By date added (oldest)"
|
||||
description="Dropdown label for sorting by date (oldest)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.dateoldest.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="nameAscending"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By name (ascending)"
|
||||
description="Dropdown label for sorting by name (ascending)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.nameascending.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
key="nameDescending"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="By name (descending)"
|
||||
description="Dropdown label for sorting by name (descending)"
|
||||
id="authoring.texteditor.selectimagemodal.sort.namedescending.label"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
</ActionRow>
|
||||
`;
|
||||
@@ -5,8 +5,7 @@ import { Button, Stack } from '@edx/paragon';
|
||||
import { Add } from '@edx/paragon/icons';
|
||||
import {
|
||||
FormattedMessage,
|
||||
injectIntl,
|
||||
intlShape,
|
||||
useIntl,
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
|
||||
import BaseModal from '../BaseModal';
|
||||
@@ -33,9 +32,8 @@ export const SelectionModal = ({
|
||||
isLoaded,
|
||||
isFetchError,
|
||||
isUploadError,
|
||||
// injected
|
||||
intl,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const {
|
||||
confirmMsg,
|
||||
uploadButtonMsg,
|
||||
@@ -54,7 +52,6 @@ export const SelectionModal = ({
|
||||
|
||||
const galleryPropsValues = {
|
||||
isLoaded,
|
||||
show: showGallery,
|
||||
...galleryProps,
|
||||
};
|
||||
return (
|
||||
@@ -109,7 +106,7 @@ export const SelectionModal = ({
|
||||
<FormattedMessage {...galleryError.message} />
|
||||
</ErrorAlert>
|
||||
<Stack gap={2}>
|
||||
<Gallery {...galleryPropsValues} />
|
||||
{showGallery && <Gallery {...galleryPropsValues} />}
|
||||
<FileInput fileInput={fileInput} acceptedFiles={Object.values(acceptedFiles).join()} />
|
||||
</Stack>
|
||||
</BaseModal>
|
||||
@@ -155,8 +152,6 @@ SelectionModal.propTypes = {
|
||||
isLoaded: PropTypes.bool.isRequired,
|
||||
isFetchError: PropTypes.bool.isRequired,
|
||||
isUploadError: PropTypes.bool.isRequired,
|
||||
// injected
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
export default injectIntl(SelectionModal);
|
||||
export default SelectionModal;
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import React from 'react';
|
||||
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { formatMessage } from '../../../testUtils';
|
||||
|
||||
import SelectionModal from '.';
|
||||
import '@testing-library/jest-dom';
|
||||
|
||||
const props = {
|
||||
isOpen: jest.fn(),
|
||||
isClose: jest.fn(),
|
||||
isOpen: true,
|
||||
close: jest.fn(),
|
||||
size: 'fullscreen',
|
||||
isFullscreenScroll: false,
|
||||
galleryError: {
|
||||
@@ -35,7 +36,13 @@ const props = {
|
||||
click: 'imgHooks.fileInput.click',
|
||||
ref: 'imgHooks.fileInput.ref',
|
||||
},
|
||||
galleryProps: { gallery: 'props' },
|
||||
galleryProps: {
|
||||
gallery: 'props',
|
||||
emptyGalleryLabel: {
|
||||
id: 'emptyGalleryMsg',
|
||||
defaultMessage: 'Empty Gallery',
|
||||
},
|
||||
},
|
||||
searchSortProps: { search: 'sortProps' },
|
||||
selectBtnProps: { select: 'btnProps' },
|
||||
acceptedFiles: { png: '.png' },
|
||||
@@ -69,7 +76,6 @@ const props = {
|
||||
isLoaded: true,
|
||||
isFetchError: false,
|
||||
isUploadError: false,
|
||||
intl: { formatMessage },
|
||||
};
|
||||
|
||||
const mockGalleryFn = jest.fn();
|
||||
@@ -105,7 +111,7 @@ describe('Selection Modal', () => {
|
||||
});
|
||||
test('rendering correctly with expected Input', async () => {
|
||||
render(
|
||||
<IntlProvider>
|
||||
<IntlProvider locale="en">
|
||||
<SelectionModal {...props} />
|
||||
</IntlProvider>,
|
||||
);
|
||||
@@ -118,7 +124,6 @@ describe('Selection Modal', () => {
|
||||
expect.objectContaining({
|
||||
...props.galleryProps,
|
||||
isLoaded: props.isLoaded,
|
||||
show: true,
|
||||
}),
|
||||
);
|
||||
expect(mockFetchErrorAlertFn).toHaveBeenCalledWith(
|
||||
@@ -142,11 +147,11 @@ describe('Selection Modal', () => {
|
||||
});
|
||||
test('rendering correctly with errors', () => {
|
||||
render(
|
||||
<IntlProvider>
|
||||
<IntlProvider locale="en">
|
||||
<SelectionModal {...props} isFetchError />
|
||||
</IntlProvider>,
|
||||
);
|
||||
expect(screen.getByText('Gallery')).toBeInTheDocument();
|
||||
expect(screen.queryByText('Gallery')).not.toBeInTheDocument();
|
||||
expect(screen.getByText('FileInput')).toBeInTheDocument();
|
||||
expect(screen.getByText('FetchErrorAlert')).toBeInTheDocument();
|
||||
expect(screen.getByText('UploadErrorAlert')).toBeInTheDocument();
|
||||
@@ -157,17 +162,10 @@ describe('Selection Modal', () => {
|
||||
message: props.modalMessages.fetchError,
|
||||
}),
|
||||
);
|
||||
expect(mockGalleryFn).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
...props.galleryProps,
|
||||
isLoaded: props.isLoaded,
|
||||
show: false,
|
||||
}),
|
||||
);
|
||||
});
|
||||
test('rendering correctly with loading', () => {
|
||||
render(
|
||||
<IntlProvider>
|
||||
<IntlProvider locale="en">
|
||||
<SelectionModal {...props} isLoaded={false} />
|
||||
</IntlProvider>,
|
||||
);
|
||||
@@ -180,7 +178,6 @@ describe('Selection Modal', () => {
|
||||
expect.objectContaining({
|
||||
...props.galleryProps,
|
||||
isLoaded: false,
|
||||
show: true,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -4,6 +4,11 @@ export const messages = {
|
||||
defaultMessage: 'Search',
|
||||
description: 'Placeholder text for search bar',
|
||||
},
|
||||
clearSearch: {
|
||||
id: 'authoring.selectionmodal.search.clearSearchButton',
|
||||
defaultMessage: 'Clear search query',
|
||||
description: 'Button to clear search query',
|
||||
},
|
||||
emptySearchLabel: {
|
||||
id: 'authoring.selectionmodal.emptySearchLabel',
|
||||
defaultMessage: 'No search results.',
|
||||
|
||||
Reference in New Issue
Block a user