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

replaces ember-render-modifiers with custom modifier in DatePicker component #8312

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
2 changes: 0 additions & 2 deletions packages/ilios-common/.lint-todo
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
add|ember-template-lint|no-at-ember-render-modifiers|5|2|5|2|fb8a149d14413d4dfc84ffd31349ef3f2ac6d17b|1731542400000|1762646400000|1793750400000|addon/components/date-picker.hbs
add|ember-template-lint|no-at-ember-render-modifiers|6|2|6|2|993f1e23f796f19a221eae6e24872755e0436cb4|1731542400000|1762646400000|1793750400000|addon/components/date-picker.hbs
add|ember-template-lint|no-at-ember-render-modifiers|6|8|6|8|c628ee621a6e921e369bf6bcb158a5ef932e6741|1731542400000|1762646400000|1793750400000|addon/components/editable-field.hbs
add|ember-template-lint|no-at-ember-render-modifiers|2|2|2|2|ad17d66e0fe1720bc8ddedc12dff3a105709765c|1731542400000|1762646400000|1793750400000|addon/components/html-editor.hbs
add|ember-template-lint|no-at-ember-render-modifiers|3|2|3|2|d39abab22a3e75d93f69335da422e7ef73b36283|1731542400000|1762646400000|1793750400000|addon/components/html-editor.hbs
Expand Down
5 changes: 2 additions & 3 deletions packages/ilios-common/addon/components/date-picker.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
aria-label={{t "general.pickADate"}}
class="date-picker"
data-test-date-picker
{{did-insert (perform this.setupPicker)}}
{{did-update (perform this.updatePicker) @value @maxDate @minDate}}
{{date-picker @value @minDate @maxDate this.intl.primaryLocale @onChange}}
...attributes
/>
/>
66 changes: 0 additions & 66 deletions packages/ilios-common/addon/components/date-picker.js
Original file line number Diff line number Diff line change
@@ -1,72 +1,6 @@
import Component from '@glimmer/component';
import { service } from '@ember/service';
import { dropTask, restartableTask, waitForProperty } from 'ember-concurrency';
import { tracked } from '@glimmer/tracking';
import flatpickr from 'flatpickr';
import { later, next } from '@ember/runloop';
import { isTesting } from '@embroider/macros';

export default class DatePickerComponent extends Component {
@service intl;

@tracked _flatPickerInstance;
@tracked isOpen = false;

updatePicker = restartableTask(async (element, [value]) => {
await waitForProperty(this, '_flatPickerInstance');
if (this._flatPickerInstance.selectedDates[0] != value) {
this._flatPickerInstance.setDate(value);
}
});

setupPicker = dropTask(async (element) => {
const currentLocale = this.intl.primaryLocale;
let locale;
switch (currentLocale) {
case 'fr':
// eslint-disable-next-line no-case-declarations
const { French } = await import('flatpickr/dist/l10n/fr.js');
locale = French;
break;
case 'es':
// eslint-disable-next-line no-case-declarations
const { Spanish } = await import('flatpickr/dist/l10n/es.js');
locale = Spanish;
break;
default:
locale = 'en';
}
this._flatPickerInstance = flatpickr(element, {
locale,
defaultDate: this.args.value,
formatDate: (dateObj) =>
this.intl.formatDate(dateObj, { day: '2-digit', month: '2-digit', year: 'numeric' }),
onChange: (selectedDates) => this.onChange(selectedDates[0]),
onOpen: () => {
// eslint-disable-next-line ember/no-runloop
later(() => {
this.isOpen = true;
}, 250);
},
onClose: () => {
this.isOpen = false;
},
maxDate: this.args.maxDate ?? null,
minDate: this.args.minDate ?? null,
disableMobile: isTesting(),
});
});

willDestroy() {
super.willDestroy(...arguments);
if (this._flatPickerInstance) {
this._flatPickerInstance.destroy();
}
}

async onChange(date) {
await this.args.onChange(date);
// eslint-disable-next-line ember/no-runloop
await next(() => {});
}
}
84 changes: 84 additions & 0 deletions packages/ilios-common/addon/modifiers/date-picker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import Modifier from 'ember-modifier';
import { registerDestructor } from '@ember/destroyable';
import flatpickr from 'flatpickr';
import { French } from 'flatpickr/dist/l10n/fr.js';
import { Spanish } from 'flatpickr/dist/l10n/es.js';
import { isTesting } from '@embroider/macros';
import { service } from '@ember/service';

function cleanup(instance) {
instance.locale = null;
instance.onChangeHandler = null;
if (instance.flatpickr) {
instance.flatpickr.destroy();
instance.flatpickr = null;
}
}

export default class DatePickerModifier extends Modifier {
@service intl;
flatpickr = null;
locale = null;
onChangeHandler = null;

constructor(owner, args) {
super(owner, args);
registerDestructor(this, cleanup);
}

modify(element, [value, minDate, maxDate, locale, onChangeHandler]) {
// We only need to set this once.
if (!this.onChangeHandler) {
this.onChangeHandler = onChangeHandler;
}
if (!this.flatpickr) {
this.flatpickr = this.initPicker(element, value, minDate, maxDate, locale);
this.locale = locale;
}

if (this.flatpickr.selectedDates[0] !== value) {
this.flatpickr.setDate(value);
}
if (this.flatpickr.minDate !== minDate) {
this.flatpickr.set('minDate', minDate);
}
if (this.flatpickr.maxDate !== maxDate) {
this.flatpickr.set('maxDate', maxDate);
}

if (this.locale !== locale) {
this.locale = locale;
this.flatpickr.set('locale', this.getFlatpickrLocale(locale));
}
}

// @see https://flatpickr.js.org/localization/
getFlatpickrLocale(localeIdentifier) {
switch (localeIdentifier) {
case 'fr':
return French;
case 'es':
return Spanish;
default:
return 'en';
}
}

initPicker(element, value, minDate, maxDate, locale) {
return flatpickr(element, {
locale: this.getFlatpickrLocale(locale),
defaultDate: value,
formatDate: (dateObj) =>
this.intl.formatDate(dateObj, { day: '2-digit', month: '2-digit', year: 'numeric' }),
onChange: (selectedDates) => this.onChange(selectedDates[0]),
maxDate: maxDate ?? null,
minDate: minDate ?? null,
disableMobile: isTesting(),
});
}
async onChange(date) {
if (this.onChangeHandler) {
await this.onChangeHandler(date);
}
}
}
1 change: 1 addition & 0 deletions packages/ilios-common/app/modifiers/date-picker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from 'ilios-common/modifiers/date-picker';
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'test-app/tests/helpers';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';

// todo: flesh this out. [ST 2025/01/19]
module('Integration | Modifier | date-picker', function (hooks) {
setupRenderingTest(hooks);

test('it works with minimal input', async function (assert) {
this.set('value', Date.now());
this.set('minDate', null);
this.set('maxDate', null);
this.set('locale', 'en');
await render(
hbs`<div {{date-picker this.value this.minDate this.maxDate this.locale (noop)}}></div>`,
);
// todo: add more test assertions here.
assert.ok(true);
});
});
Loading