Skip to content

Commit

Permalink
Upgrade date picker
Browse files Browse the repository at this point in the history
  • Loading branch information
jordisala1991 committed Apr 25, 2023
1 parent a437685 commit 80643d6
Show file tree
Hide file tree
Showing 175 changed files with 20,138 additions and 13,283 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ module.exports = {
env: {
browser: true,
jquery: true,
'jest/globals': true,
},
plugins: ['header'],
plugins: ['header', 'jest'],
rules: {
'header/header': [
2,
Expand Down
24 changes: 22 additions & 2 deletions .github/workflows/frontend.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ permissions:
contents: read

jobs:
webpack-encore:
build:
name: Webpack Encore

runs-on: ubuntu-latest
Expand All @@ -29,7 +29,7 @@ jobs:
- name: Install Node
uses: actions/setup-node@v3
with:
node-version: '16'
node-version: '18'

- name: Install NPM dependencies
uses: bahmutov/npm-install@v1
Expand All @@ -48,3 +48,23 @@ jobs:

- name: Check if the compilation is up to date
run: git diff --no-patch --exit-code

test:
name: Jest

runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Install Node
uses: actions/setup-node@v3
with:
node-version: '18'

- name: Install NPM dependencies
uses: bahmutov/npm-install@v1

- name: Run Jest
run: npx jest
2 changes: 1 addition & 1 deletion .stylelintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

module.exports = {
customSyntax: 'postcss-scss',
extends: ['stylelint-config-standard', 'stylelint-config-prettier'],
extends: ['stylelint-config-standard'],
plugins: ['stylelint-scss', 'stylelint-order'],
rules: {
'at-rule-no-unknown': null,
Expand Down
13 changes: 4 additions & 9 deletions assets/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,9 @@
// Any SCSS/CSS you require will output into a single css file (app.css in this case)
import '../scss/app.scss';

import moment from 'moment';
// eslint-disable-next-line import/no-unresolved, import/no-webpack-loader-syntax
import DatePicker from '@symfony/stimulus-bridge/lazy-controller-loader?lazy=true!./controllers/datepicker_controller.js';

// Eonasdan Bootstrap DateTimePicker in its version 3 does not
// provide the scss or plain css, it only provides the less version
// of its source files, that's why it is not included it via npm.
import '../vendor/bootstrap-datetimepicker';
const { sonataApplication } = global;

// Create global moment variable to be used by the locale script.
// It expects moment to be available on the global scope
// in order to define the requested locale translations
global.moment = moment;
sonataApplication.register('datepicker', DatePicker);
42 changes: 42 additions & 0 deletions assets/js/controllers/datepicker_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*!
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

import { Controller } from '@hotwired/stimulus';
import Flatpickr from 'flatpickr';
import l10n from 'flatpickr/dist/l10n';

export default class extends Controller {
static values = {
options: Object,
};

initialize() {
const { lang: locale } = document.documentElement;

this.dispatchEvent('datepicker:pre-initialize', { locale });

if (locale in l10n) {
Flatpickr.localize(l10n[locale]);
}
}

connect() {
const options = this.optionsValue;

this.dispatchEvent('datepicker:pre-connect', { options });

const datePicker = new Flatpickr(this.element, options);

this.dispatchEvent('datepicker:connect', { datePicker });
}

dispatchEvent(name, payload) {
this.element.dispatchEvent(new CustomEvent(name, { detail: payload }));
}
}
176 changes: 176 additions & 0 deletions assets/js/controllers/datepicker_controller.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
/*!
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

import { Application, Controller } from '@hotwired/stimulus';
import { getByTestId, waitFor } from '@testing-library/dom';
import userEvent from '@testing-library/user-event';
import Flatpickr from 'flatpickr';
import DatepickerController from './datepicker_controller';

class CheckController extends Controller {
initialize() {
this.element.addEventListener('datepicker:pre-initialize', () => {
this.element.classList.add('pre-initialized');
});
}

connect() {
this.element.addEventListener('datepicker:pre-connect', () => {
this.element.classList.add('pre-connected');
});

this.element.addEventListener('datepicker:connect', () => {
this.element.classList.add('connected');
});
}
}

const startStimulus = () => {
const application = Application.start();

application.register('check', CheckController);
application.register('datepicker', DatepickerController);
};

const flatpickrCalendar = () => document.querySelector('.flatpickr-calendar');

describe('DatepickerController', () => {
it('connect without options', async () => {
document.body.innerHTML = `
<input
type="text"
data-testid="main-element"
data-controller="check datepicker"
/>
`;

const mainElement = getByTestId(document, 'main-element');

expect(mainElement).not.toHaveClass('pre-initialized');
expect(mainElement).not.toHaveClass('pre-connected');
expect(mainElement).not.toHaveClass('connected');

startStimulus();

await waitFor(() => {
expect(mainElement).toHaveClass('pre-initialized');
expect(mainElement).toHaveClass('pre-connected');
expect(mainElement).toHaveClass('connected');
});
});

it('initializes flatpickr', async () => {
document.body.innerHTML = `
<input
type="text"
data-testid="main-element"
data-controller="check datepicker"
/>
`;

const mainElement = getByTestId(document, 'main-element');

startStimulus();

await waitFor(() => {
expect(mainElement).toHaveClass('connected');
});

expect(mainElement).toHaveClass('flatpickr-input');
});

it('can be opened', async () => {
document.body.innerHTML = `
<input
type="text"
data-testid="main-element"
data-controller="check datepicker"
/>
`;

const mainElement = getByTestId(document, 'main-element');

startStimulus();

await waitFor(() => {
expect(mainElement).toHaveClass('connected');
});

expect(flatpickrCalendar()).not.toHaveClass('open');

await userEvent.click(mainElement);

expect(flatpickrCalendar()).toHaveClass('open');
});

it('can receive options', async () => {
document.body.innerHTML = `
<input
type="text"
data-testid="main-element"
data-controller="check datepicker"
data-datepicker-options-value='${JSON.stringify({ enableTime: true })}'
/>
`;

startStimulus();

await waitFor(() => {
expect(getByTestId(document, 'main-element')).toHaveClass('connected');
});

expect(flatpickrCalendar()).toHaveClass('hasTime');
});

it('can be localized', async () => {
document.documentElement.lang = 'fr';
document.body.innerHTML = `
<input
type="text"
data-testid="main-element"
data-controller="check datepicker"
/>
`;

startStimulus();

await waitFor(() => {
expect(getByTestId(document, 'main-element')).toHaveClass('connected');
});

expect(Flatpickr.l10ns.default).toEqual(expect.objectContaining(Flatpickr.l10ns.fr));
});

it('can select a date', async () => {
document.body.innerHTML = `
<input
type="text"
data-testid="main-element"
data-controller="check datepicker"
/>
`;

const mainElement = getByTestId(document, 'main-element');

startStimulus();

await waitFor(() => {
expect(mainElement).toHaveClass('connected');
});

await userEvent.click(mainElement);

expect(mainElement.value).toBe('');

await userEvent.click(document.querySelector('.flatpickr-day'));

expect(flatpickrCalendar()).not.toHaveClass('open');
expect(mainElement.value).not.toBe('');
});
});
13 changes: 13 additions & 0 deletions assets/js/controllers/setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*!
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

// eslint-disable-next-line import/no-extraneous-dependencies
import 'regenerator-runtime/runtime';
// eslint-disable-next-line import/no-extraneous-dependencies
import '@testing-library/jest-dom';
5 changes: 1 addition & 4 deletions assets/scss/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,4 @@
* file that was distributed with this source code.
*/

// Eonasdan Bootstrap DateTimePicker in its version 3 does not
// provide the scss or plain css, it only provides the less version
// of its source files, that's why it is not included it via npm.
@import '../vendor/bootstrap-datetimepicker.min.css';
@import url('flatpickr');
Loading

0 comments on commit 80643d6

Please sign in to comment.