Using global util function for displaying date in listing dashboard (#10244)
* Common date util function for listing dashboard * Making dateTime required * Fixing typo * Fixing tests * Fixing deletion of function in globalThis
This commit is contained in:
parent
2bc1496bc4
commit
ea74a3d390
5 changed files with 135 additions and 38 deletions
|
|
@ -13,7 +13,7 @@
|
|||
for more information.
|
||||
*/
|
||||
function timestampToLocalDateTime(timestamp, locale, options) {
|
||||
if (timestamp === '') {
|
||||
if (!timestamp) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
|
@ -26,17 +26,6 @@ function timestampToLocalDateTime(timestamp, locale, options) {
|
|||
}
|
||||
|
||||
function addLocalizedDateTimeToElementsTitles(elements, timestampAttribute) {
|
||||
// example: "Wednesday, April 3, 2019, 2:55:14 PM"
|
||||
var timeOptions = {
|
||||
weekday: 'long',
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
second: 'numeric',
|
||||
};
|
||||
|
||||
for (var i = 0; i < elements.length; i += 1) {
|
||||
var element = elements[i];
|
||||
|
||||
|
|
@ -48,11 +37,7 @@ function addLocalizedDateTimeToElementsTitles(elements, timestampAttribute) {
|
|||
// `navigator.language` is used to allow the date to be localized
|
||||
// according to the browser's locale
|
||||
// see <https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/language>
|
||||
var localDateTime = timestampToLocalDateTime(
|
||||
timestamp,
|
||||
navigator.language,
|
||||
timeOptions,
|
||||
);
|
||||
var localDateTime = timestampToLocalDateTimeLong(timestamp);
|
||||
element.setAttribute('title', localDateTime);
|
||||
}
|
||||
}
|
||||
|
|
@ -74,3 +59,45 @@ function localizeTimeElements(elements, timeOptions) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
function timestampToLocalDateTimeLong(timestamp) {
|
||||
// example: "Wednesday, April 3, 2019, 2:55:14 PM"
|
||||
|
||||
return timestampToLocalDateTime(timestamp, navigator.language, {
|
||||
weekday: 'long',
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
second: 'numeric',
|
||||
});
|
||||
}
|
||||
|
||||
function timestampToLocalDateTimeShort(timestamp) {
|
||||
// example: "10 Dec 2018" if it is not the current year
|
||||
// example: "6 Sep" if it is the current year
|
||||
|
||||
if (timestamp) {
|
||||
const currentYear = new Date().getFullYear();
|
||||
const givenYear = new Date(timestamp).getFullYear();
|
||||
|
||||
var timeOptions = {
|
||||
day: 'numeric',
|
||||
month: 'short',
|
||||
};
|
||||
|
||||
if (givenYear !== currentYear) {
|
||||
timeOptions.year = 'numeric';
|
||||
}
|
||||
|
||||
return timestampToLocalDateTime(timestamp, navigator.language, timeOptions);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
if (typeof globalThis !== 'undefined') {
|
||||
globalThis.timestampToLocalDateTimeLong = timestampToLocalDateTimeLong; // eslint-disable-line no-undef
|
||||
globalThis.timestampToLocalDateTimeShort = timestampToLocalDateTimeShort; // eslint-disable-line no-undef
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@ import { h } from 'preact';
|
|||
import { render, fireEvent } from '@testing-library/preact';
|
||||
import { JSDOM } from 'jsdom';
|
||||
import { axe } from 'jest-axe';
|
||||
|
||||
import '../../../assets/javascripts/utilities/localDateTime';
|
||||
|
||||
import { ListingDashboard } from '../listingDashboard';
|
||||
|
||||
const doc = new JSDOM('<!doctype html><html><body></body></html>');
|
||||
|
|
@ -180,7 +183,15 @@ const listings = {
|
|||
selectedListings: 'user',
|
||||
};
|
||||
|
||||
/* eslint-disable no-unused-vars */
|
||||
/* global globalThis timestampToLocalDateTimeLong timestampToLocalDateTimeShort */
|
||||
|
||||
describe('<ListingDashboard />', () => {
|
||||
afterAll(() => {
|
||||
delete globalThis.timestampToLocalDateTimeLong;
|
||||
delete globalThis.timestampToLocalDateTimeShort;
|
||||
});
|
||||
|
||||
it('should have no a11y violations', async () => {
|
||||
const { container } = render(<ListingDashboard />);
|
||||
const results = await axe(container);
|
||||
|
|
@ -227,7 +238,7 @@ describe('<ListingDashboard />', () => {
|
|||
};
|
||||
|
||||
getByText('asdfasdf (expired)', listing1GetByTextOptions);
|
||||
getByText('Jun 11', listing1GetByTextOptions);
|
||||
getByText('Jun 11, 2019', listing1GetByTextOptions);
|
||||
|
||||
// listing category
|
||||
const listing1CfpCategory = getByText('cfp', listing1GetByTextOptions);
|
||||
|
|
@ -265,7 +276,7 @@ describe('<ListingDashboard />', () => {
|
|||
};
|
||||
|
||||
getByText('YOYOYOYOYOOOOOOOO (expired)', listing2GetByTextOptions);
|
||||
getByText('May 11', listing2GetByTextOptions);
|
||||
getByText('May 11, 2019', listing2GetByTextOptions);
|
||||
|
||||
// listing category
|
||||
const listing2EventsCategory = getByText(
|
||||
|
|
@ -318,7 +329,7 @@ describe('<ListingDashboard />', () => {
|
|||
};
|
||||
|
||||
getByText('hehhehe (expired)', listing3GetByTextOptions);
|
||||
getByText('Apr 11', listing3GetByTextOptions);
|
||||
getByText('Apr 11, 2019', listing3GetByTextOptions);
|
||||
|
||||
// listing category
|
||||
const listing3CfpCategory = getByText('cfp', listing3GetByTextOptions);
|
||||
|
|
|
|||
|
|
@ -1,28 +1,20 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import { h } from 'preact';
|
||||
|
||||
import DateTime from '../../../shared/components/dateTime';
|
||||
|
||||
const ListingDate = ({ bumpedAt, updatedAt }) => {
|
||||
|
||||
const listingDate = bumpedAt
|
||||
? new Date(bumpedAt.toString()).toLocaleDateString('default', {
|
||||
day: '2-digit',
|
||||
month: 'short',
|
||||
})
|
||||
: new Date(updatedAt.toString()).toLocaleDateString('default', {
|
||||
day: '2-digit',
|
||||
month: 'short',
|
||||
});
|
||||
|
||||
return (
|
||||
<span className="dashboard-listing-date">
|
||||
{listingDate}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
<DateTime
|
||||
className="dashboard-listing-date"
|
||||
dateTime={bumpedAt ? bumpedAt.toString() : updatedAt.toString()}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
ListingDate.propTypes = {
|
||||
bumpedAt: PropTypes.instanceOf(Date).isRequired,
|
||||
updatedAt: PropTypes.instanceOf(Date).isRequired,
|
||||
}
|
||||
};
|
||||
|
||||
export default ListingDate;
|
||||
export default ListingDate;
|
||||
|
|
|
|||
42
app/javascript/shared/components/__tests__/dateTime.test.jsx
Normal file
42
app/javascript/shared/components/__tests__/dateTime.test.jsx
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import { h } from 'preact';
|
||||
import { axe } from 'jest-axe';
|
||||
import { render } from '@testing-library/preact';
|
||||
import '@testing-library/jest-dom';
|
||||
import DateTime from '../dateTime';
|
||||
|
||||
import '../../../../assets/javascripts/utilities/localDateTime';
|
||||
|
||||
/* eslint-disable no-unused-vars */
|
||||
/* global globalThis timestampToLocalDateTimeLong timestampToLocalDateTimeShort */
|
||||
|
||||
describe('<DateTime />', () => {
|
||||
it('should have no a11y violations', async () => {
|
||||
afterAll(() => {
|
||||
delete globalThis.timestampToLocalDateTimeLong;
|
||||
delete globalThis.timestampToLocalDateTimeShort;
|
||||
});
|
||||
|
||||
const { container } = render(
|
||||
<DateTime
|
||||
className={'date-time'}
|
||||
dateTime={new Date('2019-09-20T17:26:20.531Z')}
|
||||
/>,
|
||||
);
|
||||
const results = await axe(container);
|
||||
|
||||
expect(results).toHaveNoViolations();
|
||||
});
|
||||
|
||||
it('should render given datetime', () => {
|
||||
const { getByText } = render(
|
||||
<DateTime
|
||||
className={'date-time'}
|
||||
dateTime={new Date('2019-09-10T17:26:20.531Z')}
|
||||
/>,
|
||||
);
|
||||
|
||||
const dateTime = getByText('Sep 10, 2019');
|
||||
expect(dateTime.title).toBe('Tuesday, September 10, 2019, 5:26:20 PM');
|
||||
expect(dateTime).toHaveClass('date-time');
|
||||
});
|
||||
});
|
||||
25
app/javascript/shared/components/dateTime.jsx
Normal file
25
app/javascript/shared/components/dateTime.jsx
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/* global timestampToLocalDateTimeLong timestampToLocalDateTimeShort */
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import { h } from 'preact';
|
||||
|
||||
const DateTime = ({ dateTime, className }) => (
|
||||
<time
|
||||
dateTime={dateTime}
|
||||
title={timestampToLocalDateTimeLong(dateTime)}
|
||||
className={className}
|
||||
>
|
||||
{timestampToLocalDateTimeShort(dateTime)}
|
||||
</time>
|
||||
);
|
||||
|
||||
DateTime.defaultProps = {
|
||||
className: '',
|
||||
};
|
||||
|
||||
DateTime.propTypes = {
|
||||
dateTime: PropTypes.instanceOf(Date).isRequired,
|
||||
className: PropTypes.string,
|
||||
};
|
||||
|
||||
export default DateTime;
|
||||
Loading…
Add table
Reference in a new issue