Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use luxon #519

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 20 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![Ember Observer Score](https://emberobserver.com/badges/ember-pikaday.svg)](https://emberobserver.com/addons/ember-pikaday)
[![NPM](https://badgen.net/npm/v/ember-pikaday)](https://www.npmjs.com/package/ember-pikaday)

ember-pikaday is an addon that can be installed with Ember CLI. It gives you a datepicker input component that can be used in your Ember.js application. [ember-cli-moment-shim](https://github.com/jasonmit/ember-cli-moment-shim) is used in the background so it is added as NPM dependencies to your application.
ember-pikaday is an addon that can be installed with Ember CLI. It gives you a datepicker input component that can be used in your Ember.js application.

**The component provided by ember-pikaday is fully acceptance tested. It also provides test helpers to interact with the datepicker in your own acceptance tests. It works in Ember 1.13.1+ or 2.0+, including beta and canary.**

Expand Down Expand Up @@ -44,12 +44,12 @@ You can also pass in other closure actions to handle `onOpen`, `onClose` and `on
</label>
```

You can also change the default format from `DD.MM.YYYY` to any format string supported by Moment.js.
You can also change the default format from `dd.LL.yyyy` to any format string supported by Luxon. (https://moment.github.io/luxon/docs/manual/formatting.html#table-of-tokens)

```handlebars
<label>
Start date:
<PikadayInput @format={{"MM/DD/YYYY"}}/>
<PikadayInput @format={{"LL/dd/yyyy"}}/>
</label>
```

Expand Down Expand Up @@ -120,8 +120,8 @@ If the datepicker is shown to the user and it gets disabled it will close the da
The `firstDay` attribute is supported as a binding so you can set the first day of the calendar week.
Defaults to Monday.

- 0 = Sunday
- 1 = Monday
- 0 = Monday
- 1 = Tuesday
- etc...

```handlebars
Expand Down Expand Up @@ -180,33 +180,35 @@ If you don't want to show an input field, you can use the `pikaday-inputless` co

## Localization

Localizing the datepicker is possible in two steps. To localize the output of the datepicker, this is the formatted string visible in the input field, you simply include all the locales by following the [ember-cli-moment-shim instructions](https://github.com/jasonmit/ember-cli-moment-shim#cherry-pick-locales-optimal) and include the following in your `ember-cli-build.js`

```js
app.import('node_modules/moment/locale/de.js');
```

To localize the datepicker itself, this is the popup you see after clicking the input, a little more work is necessary. The prefered way to do this is writting a custom initializer to inject a localized `i18n` object into the datepicker component. Naturally you can use your own localized strings instead of the ones provided by Moment.js.
To localize the datepicker itself, this is the popup you see after clicking the input, a little more work is necessary. The prefered way to do this is writting a custom initializer to inject a localized `i18n` object into the datepicker component. Naturally you can use your own localized strings instead of the ones provided by Luxon.

```js
// app/initializers/setup-pikaday-i18n.js

import EmberObject from '@ember/object';
import moment from 'moment';
import { Info } from 'luxon';

export default {
name: 'setup-pikaday-i18n',
initialize: function(application) {
let i18n = EmberObject.extend({
const i18n = EmberObject.extend({
previousMonth: 'Vorheriger Monat',
nextMonth: 'Nächster Monat',
months: moment.localeData().months(),
weekdays: moment.localeData().weekdays(),
weekdaysShort: moment.localeData().weekdaysShort()
months: Info.months(),
weekdays: Info.weekdays(),
weekdaysShort: Info.weekdays('short')
});

application.register('pikaday-i18n:main', i18n, { singleton: true });
const container = arguments[0];
const application = arguments[1] || container;

container.register('pikaday-i18n:main', i18n, { singleton: true });
application.inject('component:pikaday-input', 'i18n', 'pikaday-i18n:main');
application.inject(
'component:pikaday-inputless',
'i18n',
'pikaday-i18n:main'
);
}
};
```
Expand Down
31 changes: 18 additions & 13 deletions addon/mixins/pikaday.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { assign } from '@ember/polyfills';
import { isPresent } from '@ember/utils';
import { run, next } from '@ember/runloop';
import { getProperties, computed } from '@ember/object';
import moment from 'moment';
import { DateTime } from 'luxon';

export default Mixin.create({
_options: computed('options', 'i18n', {
Expand Down Expand Up @@ -63,8 +63,11 @@ export default Mixin.create({
onClose: run.bind(this, this.onPikadayClose),
onSelect: run.bind(this, this.onPikadaySelect),
onDraw: run.bind(this, this.onPikadayRedraw),
firstDay: typeof firstDay !== 'undefined' ? parseInt(firstDay, 10) : 1,
format: this.get('format') || 'DD.MM.YYYY',
firstDay: typeof firstDay !== 'undefined' ? parseInt(firstDay, 10) : 0,
format: this.get('format') || 'dd.LL.yyyy',
toString: (date, format) => DateTime.fromJSDate(date).toFormat(format),
parse: (dateString, format) =>
DateTime.fromFormat(dateString, format).toJSDate(),
yearRange: this.determineYearRange(),
minDate: this.get('minDate') || null,
maxDate: this.get('maxDate') || null,
Expand Down Expand Up @@ -123,14 +126,17 @@ export default Mixin.create({
},

setPikadayDate() {
const format = 'YYYY-MM-DD';
const value = this.get('value');

if (!value) {
this.get('pikaday').setDate(value, true);
} else {
const date = this.get('useUTC')
? moment(moment.utc(value).format(format), format).toDate()
? DateTime.local(
value.getUTCFullYear(),
value.getUTCMonth() + 1,
value.getUTCDate()
).toJSDate()
: value;

this.get('pikaday').setDate(date, true);
Expand All @@ -152,7 +158,8 @@ export default Mixin.create({
next(() => {
if (
value &&
moment(value, this.get('format')).isBefore(minDate, 'day')
DateTime.fromJSDate(value).startOf('day') <
DateTime.fromJSDate(minDate).startOf('day')
) {
pikaday.setDate(minDate);
}
Expand Down Expand Up @@ -201,13 +208,11 @@ export default Mixin.create({
let selectedDate = this.get('pikaday').getDate();

if (this.get('useUTC')) {
selectedDate = moment
.utc([
selectedDate.getFullYear(),
selectedDate.getMonth(),
selectedDate.getDate()
])
.toDate();
selectedDate = DateTime.utc(
selectedDate.getFullYear(),
selectedDate.getMonth() + 1,
selectedDate.getDate()
).toJSDate();
}

this.get('onSelection')(selectedDate);
Expand Down
4 changes: 1 addition & 3 deletions blueprints/ember-pikaday/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
module.exports = {
normalizeEntityName() {},

afterInstall() {
return this.addAddonToProject('ember-cli-moment-shim', '^3.0.1');
}
afterInstall() {}
};
9 changes: 4 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,20 @@
"test:all": "ember try:each"
},
"dependencies": {
"ember-cli-babel": "^7.19.0",
"ember-cli-babel": "^7.26.6",
"ember-cli-htmlbars": "^4.3.1",
"ember-cli-moment-shim": "^3.7.1",
"luxon": "^1.27.0",
"pikaday": "^1.8.0"
},
"devDependencies": {
"@ember/optional-features": "^1.3.0",
"@glimmer/component": "^1.0.0",
"@glimmer/tracking": "^1.0.0",
"babel-eslint": "^10.0.3",
"ember-auto-import": "^2.0.1",
"ember-cli": "~3.16.0",
"ember-cli-dependency-checker": "^3.2.0",
"ember-cli-inject-live-reload": "^2.0.2",
"ember-cli-testdouble": "^0.1.3",
"ember-cli-testdouble-qunit": "^2.1.1",
"ember-disable-prototype-extensions": "^1.1.3",
"ember-load-initializers": "^2.1.1",
"ember-maybe-import-regenerator": "^0.1.6",
Expand All @@ -60,7 +59,7 @@
"qunit-dom": "^1.2.0",
"release-it": "^12.2.1",
"release-it-lerna-changelog": "^1.0.3",
"testdouble": "^3.13.1"
"webpack": "^5.40.0"
},
"engines": {
"node": "10.* || >= 12"
Expand Down
13 changes: 9 additions & 4 deletions tests/dummy/app/initializers/setup-pikaday-i18n.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
import EmberObject from '@ember/object';
import moment from 'moment';
import { Info } from 'luxon';

export default {
name: 'setup-pikaday-i18n',
initialize() {
const i18n = EmberObject.extend({
previousMonth: 'Vorheriger Monat',
nextMonth: 'Nächster Monat',
months: moment.localeData().months(),
weekdays: moment.localeData().weekdays(),
weekdaysShort: moment.localeData().weekdaysShort()
months: Info.months(),
weekdays: Info.weekdays(),
weekdaysShort: Info.weekdays('short')
});

const container = arguments[0];
const application = arguments[1] || container;

container.register('pikaday-i18n:main', i18n, { singleton: true });
application.inject('component:pikaday-input', 'i18n', 'pikaday-i18n:main');
application.inject(
'component:pikaday-inputless',
'i18n',
'pikaday-i18n:main'
);
}
};
26 changes: 13 additions & 13 deletions tests/dummy/app/templates/application.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,28 @@
{{outlet}}

Standalone datepicker:
<PikadayInput
@format="dddd MMMM Do YYYY, h:mm:ss a"
@theme="dark-theme"
@onSelection={{action "doSomethingWithSelectedValue"}}
<PikadayInput
@format="cccc LLLL d yyyy, h:mm:ss a"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need

@theme="dark-theme"
@onSelection={{action "doSomethingWithSelectedValue"}}
/>

<br>

Datepicker with minDate set to today (<Input @type="checkbox" @checked={{isMinDateSet}} />) and maxDate set to today (<Input @type="checkbox" @checked={{isMaxDateSet}} />):
<PikadayInput
@minDate={{if this.isMinDateSet this.today null}}
@maxDate={{if this.isMaxDateSet this.today null}}
@value={{someDate}}
@onSelection={{action (mut someDate)}}
<PikadayInput
@minDate={{if this.isMinDateSet this.today null}}
@maxDate={{if this.isMaxDateSet this.today null}}
@value={{someDate}}
@onSelection={{action (mut someDate)}}
/>
<br>

Datepicker with bound and set value:
<PikadayInput
@value={{this.startDate}}
@onSelection={{action (mut this.startDate)}}
@format="DD.MM.YYYY"
<PikadayInput
@value={{this.startDate}}
@onSelection={{action (mut this.startDate)}}
@format="dd.LL.yyyy"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need

/>
{{this.startDate}}
<br>
Expand Down
43 changes: 23 additions & 20 deletions tests/integration/components/pikaday-input-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { render, click, fillIn, settled } from '@ember/test-helpers';
import findAll from 'ember-pikaday/test-support/-private/find-all';
import hbs from 'htmlbars-inline-precompile';
import { close as closePikaday, Interactor } from 'ember-pikaday/test-support';
import td from 'testdouble';

const getFirstWeekendDayNumber = function() {
const date = new Date();
Expand Down Expand Up @@ -107,43 +106,46 @@ module('Integration | Component | pikaday-input', function(hooks) {
});

test('opening picker should send an action', async function(assert) {
const onOpen = td.function();
this.set('onOpen', onOpen);
const done = assert.async();
this.set('onOpen', function() {
assert.ok(true);
done();
});

await render(hbs`
<PikadayInput @onOpen={{action this.onOpen}}/>
`);

await click('input');

assert.verify(onOpen());
});

test('closing picker should send an action', async function(assert) {
const onClose = td.function();
this.set('onClose', onClose);
const done = assert.async();
this.set('onClose', function() {
assert.ok(true);
done();
});

await render(hbs`
<PikadayInput @onClose={{action this.onClose}}/>
`);

await click('input');
await closePikaday();

assert.verify(onClose());
});

test('redrawing picker should send an action', async function(assert) {
const onDraw = td.function();
this.set('onDraw', onDraw);
const done = assert.async();
this.set('onDraw', function() {
assert.ok(true);
done();
});

await render(hbs`
<PikadayInput @onDraw={{action this.onDraw}}/>
`);

await click('input');

assert.verify(onDraw());
});

test('setting the value attribute should select the correct date', async function(assert) {
Expand Down Expand Up @@ -172,7 +174,7 @@ module('Integration | Component | pikaday-input', function(hooks) {

test('format of the input is changeable', async function(assert) {
this.set('value', new Date(2010, 7, 10));
this.set('format', 'YYYY.DD.MM');
this.set('format', 'yyyy.dd.LL');

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need


await render(hbs`
<PikadayInput @value={{this.value}} @format={{this.format}}/>
Expand Down Expand Up @@ -527,7 +529,7 @@ module('Integration | Component | pikaday-input', function(hooks) {
);
});

test('firstDay defaults to Monday (1)', async function(assert) {
test('firstDay defaults to Monday', async function(assert) {
await render(hbs`
<PikadayInput/>
`);
Expand All @@ -541,7 +543,7 @@ module('Integration | Component | pikaday-input', function(hooks) {

test('firstDay option overrides the default first day value', async function(assert) {
await render(hbs`
<PikadayInput @firstDay={{0}}/>
<PikadayInput @firstDay={{6}}/>
`);

await click('input');
Expand All @@ -552,16 +554,17 @@ module('Integration | Component | pikaday-input', function(hooks) {
});

test('if an options hash is passed, default options are overridden', async function(assert) {
const onOpen = td.function();
this.set('onOpen', onOpen);
const done = assert.async();
this.set('onOpen', function() {
assert.ok(true);
done();
});

await render(hbs`
<PikadayInput @options={{hash onOpen=onOpen disableWeekends=true}}/>
`);
await click('input');

assert.verify(onOpen());

const weekendDay = getFirstWeekendDayNumber();
const disabledWeekendCell = findAll('td', document.body).find(
getDisabledDayCB(weekendDay)
Expand Down
Loading