@@ -0,0 +1,38 @@
|
||||
/*!
|
||||
* Copyright (c) 2024 PLANKA Software GmbH
|
||||
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import styles from './ExpirableTime.module.scss';
|
||||
|
||||
const DAY = 1000 * 60 * 60 * 24;
|
||||
|
||||
const isExpired = (value) => value <= Date.now() - DAY;
|
||||
|
||||
const ExpirableTime = React.memo(({ children, date, verboseDate, tooltip, ...props }) => (
|
||||
<time
|
||||
{...props} // eslint-disable-line react/jsx-props-no-spreading
|
||||
dateTime={date.toISOString()}
|
||||
title={tooltip ? verboseDate : undefined}
|
||||
className={classNames(isExpired(date) && styles.expired)}
|
||||
>
|
||||
{children}
|
||||
</time>
|
||||
));
|
||||
|
||||
ExpirableTime.propTypes = {
|
||||
children: PropTypes.string.isRequired,
|
||||
date: PropTypes.instanceOf(Date).isRequired,
|
||||
verboseDate: PropTypes.string,
|
||||
tooltip: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
ExpirableTime.defaultProps = {
|
||||
verboseDate: undefined,
|
||||
};
|
||||
|
||||
export default ExpirableTime;
|
||||
@@ -0,0 +1,10 @@
|
||||
/*!
|
||||
* Copyright (c) 2024 PLANKA Software GmbH
|
||||
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
:global(#app) {
|
||||
.expired {
|
||||
color: #cf513d;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*!
|
||||
* Copyright (c) 2024 PLANKA Software GmbH
|
||||
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
import React, { useCallback } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ReactTimeAgo from 'react-time-ago';
|
||||
|
||||
import getDateFormat from '../../../utils/get-date-format';
|
||||
import ExpirableTime from './ExpirableTime';
|
||||
|
||||
const TimeAgo = React.memo(({ date, withExpiration }) => {
|
||||
const [t, i18n] = useTranslation();
|
||||
|
||||
const verboseDateFormatter = useCallback(
|
||||
(value) =>
|
||||
t(`format:${getDateFormat(value)}`, {
|
||||
value,
|
||||
postProcess: 'formatDate',
|
||||
}),
|
||||
[t],
|
||||
);
|
||||
|
||||
return (
|
||||
<ReactTimeAgo
|
||||
date={date}
|
||||
timeStyle="round-minute"
|
||||
locale={i18n.resolvedLanguage}
|
||||
component={withExpiration ? ExpirableTime : undefined}
|
||||
formatVerboseDate={verboseDateFormatter}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
TimeAgo.propTypes = {
|
||||
date: PropTypes.instanceOf(Date).isRequired,
|
||||
withExpiration: PropTypes.bool,
|
||||
};
|
||||
|
||||
TimeAgo.defaultProps = {
|
||||
withExpiration: false,
|
||||
};
|
||||
|
||||
export default TimeAgo;
|
||||
@@ -0,0 +1,8 @@
|
||||
/*!
|
||||
* Copyright (c) 2024 PLANKA Software GmbH
|
||||
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
import TimeAgo from './TimeAgo';
|
||||
|
||||
export default TimeAgo;
|
||||
Reference in New Issue
Block a user