chore: 🤖 create relative date helper (#1276)
* chore: 🤖 create relative date helper Create a relative date helper that outputs "time" ago format. ✅ Closes: ICU-5847 * Update addons/core/addon/helpers/relative-datetime-live.js Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com> * refactor: 💡 refactor test for relative-date-helper refactor test for relative-datetime-live helper ✅ Closes: ICU-5847 Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>
This commit is contained in:
1 parent
3130831ae0
commit
a3517e53a8
9 files changed
+118
-147
No files matched your search
@@ -1 +0,0 @@
|
||||
{{this.formatted}}
|
||||
@@ -1,103 +0,0 @@
|
||||
import Component from '@glimmer/component';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
const MILLISECOND = 1;
|
||||
const SECOND = MILLISECOND * 1000;
|
||||
const MINUTE = SECOND * 60;
|
||||
const HOUR = MINUTE * 60;
|
||||
const DAY = HOUR * 24;
|
||||
const MONTH = DAY * 31;
|
||||
const YEAR = MONTH * 12;
|
||||
|
||||
// common time intervals in milliseconds
|
||||
const unitMappings = [
|
||||
{
|
||||
unit: 'second',
|
||||
value: SECOND,
|
||||
},
|
||||
{
|
||||
unit: 'minute',
|
||||
value: MINUTE,
|
||||
},
|
||||
{
|
||||
unit: 'hour',
|
||||
value: HOUR,
|
||||
},
|
||||
{
|
||||
unit: 'day',
|
||||
value: DAY,
|
||||
},
|
||||
{
|
||||
unit: 'month',
|
||||
value: MONTH,
|
||||
},
|
||||
{
|
||||
unit: 'year',
|
||||
value: YEAR,
|
||||
},
|
||||
];
|
||||
|
||||
export default class RelativeDatetimeLiveComponent extends Component {
|
||||
// =services
|
||||
|
||||
@service clockTick;
|
||||
@service intl;
|
||||
|
||||
// =properties
|
||||
|
||||
/**
|
||||
* The difference in milliseconds between the date argument and the
|
||||
* current time.
|
||||
* @type {number}
|
||||
*/
|
||||
get delta() {
|
||||
return this.args.date.valueOf() - this.clockTick.now;
|
||||
}
|
||||
|
||||
/**
|
||||
* The greatest meaningful unit is the unit which delta is equal to or
|
||||
* greater than. For example, the unit of a delta equivalent of 59 seconds is
|
||||
* 'second' while 60 seconds is 'minute', 36 hours is 'day', etc.
|
||||
* @type {object}
|
||||
*/
|
||||
get greatestMeaningfulUnit() {
|
||||
return unitMappings.reduce((currentValue, previousValue) => {
|
||||
return Math.abs(this.delta) >= previousValue.value
|
||||
? previousValue
|
||||
: currentValue;
|
||||
}, unitMappings[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The delta value scaled to the greatest meaningful unit. For example, if
|
||||
* the delta is 1000 ms, the scaled value is 1, which corresponds to
|
||||
* a GMU of 'second'. A delta of 60000 ms is also 1, corresponding to a GMU
|
||||
* of 'minute'.
|
||||
* @type {number}
|
||||
*/
|
||||
get scaledDelta() {
|
||||
if (this.delta < 0) {
|
||||
return Math.ceil(this.delta / this.greatestMeaningfulUnit.value);
|
||||
}
|
||||
return Math.floor(this.delta / this.greatestMeaningfulUnit.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* A string representation of the greatest meaningful unit.
|
||||
* @type {string}
|
||||
*/
|
||||
get unit() {
|
||||
return this.greatestMeaningfulUnit.unit;
|
||||
}
|
||||
|
||||
/**
|
||||
* A localizd relative datetime. E.g. "30 seconds ago".
|
||||
* @type {string}
|
||||
*/
|
||||
get formatted() {
|
||||
return this.intl.formatRelative(this.scaledDelta, {
|
||||
unit: this.unit,
|
||||
numeric: 'auto',
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
{{#if this.lastRefreshed}}
|
||||
<Rose::Toolbar::Info>
|
||||
<RelativeDatetimeLive @date={{this.lastRefreshed}} />
|
||||
{{relative-datetime-live this.lastRefreshed}}
|
||||
</Rose::Toolbar::Info>
|
||||
{{/if}}
|
||||
|
||||
<LoadingButton @onClick={{this.onClick}}>
|
||||
{{t 'actions.refresh'}}
|
||||
</LoadingButton>
|
||||
</LoadingButton>
|
||||
@@ -0,0 +1,68 @@
|
||||
import Helper from '@ember/component/helper';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
const MILLISECOND = 1;
|
||||
const SECOND = MILLISECOND * 1000;
|
||||
const MINUTE = SECOND * 60;
|
||||
const HOUR = MINUTE * 60;
|
||||
const DAY = HOUR * 24;
|
||||
const MONTH = DAY * 31;
|
||||
const YEAR = MONTH * 12;
|
||||
|
||||
const unitMappings = [
|
||||
{
|
||||
unit: 'second',
|
||||
value: SECOND,
|
||||
},
|
||||
{
|
||||
unit: 'minute',
|
||||
value: MINUTE,
|
||||
},
|
||||
{
|
||||
unit: 'hour',
|
||||
value: HOUR,
|
||||
},
|
||||
{
|
||||
unit: 'day',
|
||||
value: DAY,
|
||||
},
|
||||
{
|
||||
unit: 'month',
|
||||
value: MONTH,
|
||||
},
|
||||
{
|
||||
unit: 'year',
|
||||
value: YEAR,
|
||||
},
|
||||
];
|
||||
|
||||
export default class extends Helper {
|
||||
// =services
|
||||
|
||||
@service clockTick;
|
||||
@service intl;
|
||||
|
||||
// =methods
|
||||
|
||||
compute([date]) {
|
||||
const delta = date.valueOf() - this.clockTick.now;
|
||||
console.log(delta);
|
||||
const greatestMeaningfulUnit = unitMappings.reduce(
|
||||
(currentValue, previousValue) => {
|
||||
return Math.abs(delta) >= previousValue.value
|
||||
? previousValue
|
||||
: currentValue;
|
||||
},
|
||||
unitMappings[0]
|
||||
);
|
||||
const scaledDelta =
|
||||
delta < 0
|
||||
? Math.ceil(delta / greatestMeaningfulUnit.value)
|
||||
: Math.floor(delta / greatestMeaningfulUnit.value);
|
||||
const unit = greatestMeaningfulUnit.unit;
|
||||
return this.intl.formatRelative(scaledDelta, {
|
||||
unit,
|
||||
numeric: 'auto',
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from 'core/components/relative-datetime-live';
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'core/helpers/relative-datetime-live';
|
||||
@@ -1,3 +1,2 @@
|
||||
<h2 id="title">Welcome to Ember</h2>
|
||||
|
||||
<RelativeDatetimeLive @date={{this.now}} />
|
||||
<p>{{relative-datetime-live this.now}}</p>
|
||||
@@ -1,38 +0,0 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render } from '@ember/test-helpers';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
|
||||
module('Integration | Component | relative-datetime-live', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test('it renders a relative datetime', async function (assert) {
|
||||
assert.expect(6);
|
||||
|
||||
const now = Date.now();
|
||||
|
||||
this.date = now - 10 * 1000;
|
||||
await render(hbs`<RelativeDatetimeLive @date={{this.date}} />`);
|
||||
assert.dom(this.element).hasText('10 seconds ago');
|
||||
|
||||
this.date = now - 10 * 60 * 1000;
|
||||
await render(hbs`<RelativeDatetimeLive @date={{this.date}} />`);
|
||||
assert.dom(this.element).hasText('10 minutes ago');
|
||||
|
||||
this.date = now - 10 * 60 * 60 * 1000;
|
||||
await render(hbs`<RelativeDatetimeLive @date={{this.date}} />`);
|
||||
assert.dom(this.element).hasText('10 hours ago');
|
||||
|
||||
this.date = now - 10 * 24 * 60 * 60 * 1000;
|
||||
await render(hbs`<RelativeDatetimeLive @date={{this.date}} />`);
|
||||
assert.dom(this.element).hasText('10 days ago');
|
||||
|
||||
this.date = now - 10 * 31 * 24 * 60 * 60 * 1000;
|
||||
await render(hbs`<RelativeDatetimeLive @date={{this.date}} />`);
|
||||
assert.dom(this.element).hasText('10 months ago');
|
||||
|
||||
this.date = now - 10 * 12 * 31 * 24 * 60 * 60 * 1000;
|
||||
await render(hbs`<RelativeDatetimeLive @date={{this.date}} />`);
|
||||
assert.dom(this.element).hasText('10 years ago');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render } from '@ember/test-helpers';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
|
||||
module('Integration | Helper | relative-datetime-live', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test('it renders relative date in "time" ago format', async function (assert) {
|
||||
assert.expect(8);
|
||||
|
||||
const now = Date.now();
|
||||
|
||||
this.date = now - 30 * 1000;
|
||||
await render(hbs`{{relative-datetime-live this.date}}`);
|
||||
assert.dom(this.element).hasText('30 seconds ago');
|
||||
|
||||
this.date = now - 30 * 60 * 1000;
|
||||
await render(hbs`{{relative-datetime-live this.date}}`);
|
||||
assert.dom(this.element).hasText('30 minutes ago');
|
||||
|
||||
this.date = now - 23 * 60 * 60 * 1000;
|
||||
await render(hbs`{{relative-datetime-live this.date}}`);
|
||||
assert.dom(this.element).hasText('23 hours ago');
|
||||
|
||||
this.date = now - 23 * 24 * 60 * 60 * 1000;
|
||||
await render(hbs`{{relative-datetime-live this.date}}`);
|
||||
assert.dom(this.element).hasText('23 days ago');
|
||||
|
||||
this.date = now - 8 * 31 * 24 * 60 * 60 * 1000;
|
||||
await render(hbs`{{relative-datetime-live this.date}}`);
|
||||
assert.dom(this.element).hasText('8 months ago');
|
||||
|
||||
this.date = now - 23 * 12 * 31 * 24 * 60 * 60 * 1000;
|
||||
await render(hbs`{{relative-datetime-live this.date}}`);
|
||||
assert.dom(this.element).hasText('23 years ago');
|
||||
|
||||
this.date = now + 8 * 31 * 24 * 60 * 60 * 1000;
|
||||
await render(hbs`{{relative-datetime-live this.date}}`);
|
||||
assert.dom(this.element).hasText('in 7 months');
|
||||
|
||||
this.date = now + 23 * 12 * 31 * 24 * 60 * 60 * 1000;
|
||||
await render(hbs`{{relative-datetime-live this.date}}`);
|
||||
assert.dom(this.element).hasText('in 22 years');
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user