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

feat!: migrate from Moment to Tempo #1507

Merged
merged 10 commits into from
May 6, 2024
41 changes: 6 additions & 35 deletions docs/column-functionalities/Formatters.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ For a [UI sample](#ui-sample), scroll down below.
### Provided Formatters
`Slickgrid-Universal` ships with a few `Formatters` by default which helps with common fields, you can see the [entire list here](https://github.com/ghiscoding/slickgrid-universal/blob/master/packages/common/src/formatters/index.ts#L37).

> **Note** you might not need a Formatter when a simple CSS style is needed, think about using `cssClass` column property instead.
> **Note** you might not need a Formatter when a simple CSS style and class might be enough, think about using `cssClass` column property as much as possible since it has much better perf.

#### List of provided `Formatters`
- `arrayObjectToCsv`: Takes an array of complex objects converts it to a comma delimited string.
Expand All @@ -46,6 +46,7 @@ For a [UI sample](#ui-sample), scroll down below.
- `dateTimeUs` : Takes a Date object and displays it as an US Date+Time format (MM/DD/YYYY HH:mm:ss)
- `dateTimeShortUs`: Takes a Date object and displays it as an US Date+Time (without seconds) format (MM/DD/YYYY HH:mm:ss)
- `dateTimeUsAmPm` : Takes a Date object and displays it as an US Date+Time+(am/pm) format (MM/DD/YYYY hh:mm:ss a)
- `dateUtc` : Takes a Date object and displays it as a TZ format (YYYY-MM-DDThh:mm:ssZ)
- `decimal`: Display the value as x decimals formatted, defaults to 2 decimals. You can pass "minDecimal" and/or "maxDecimal" to the "params" property.
- `dollar`: Display the value as 2 decimals formatted with dollar sign '$' at the end of of the value.
- `dollarColored`: Display the value as 2 decimals formatted with dollar sign '$' at the end of of the value, change color of text to red/green on negative/positive value
Expand All @@ -70,10 +71,12 @@ For a [UI sample](#ui-sample), scroll down below.
- `translateBoolean`: Takes a boolean value, cast it to upperCase string and finally translates it (i18n).
- `tree`: Formatter that must be used when the column is a Tree Data column

**Note:** The list might not always be up to date, you can refer to the [Formatters export](https://github.com/ghiscoding/slickgrid-universal/blob/master/packages/common/src/formatters/index.ts#L37) to know exactly which ones are available.
> **Note:** The list is certainly not up to date (especially for Dates), please refer to the [Formatters export](https://github.com/ghiscoding/slickgrid-universal/blob/master/packages/common/src/formatters/index.ts#L37) to know exactly which formatters are available.

> **Note** all Date formatters are formatted using [Tempo](https://tempo.formkit.com/#format-tokens). There are also many more Date formats not shown above, simply visit the [formatters.index](https://github.com/ghiscoding/slickgrid-universal/blob/master/packages/common/src/formatters/formatters.index.ts#L101) to see all available Date/Time formats.

### Usage
To use any of them, you need to import `Formatters` from `Slickgrid-Universal` and add a `formatter: ...` in your column definitions as shown below:
To use any of them, you simply need to import `Formatters` from `Slickgrid-Universal` and add a `formatter: Formatters.xyz` (where `xyx` is the name of the built-in formatter) in your column definitions as shown below:

#### TypeSript
```ts
Expand Down Expand Up @@ -102,38 +105,6 @@ export class Example {
}
```

#### SalesForce (ES6)
For SalesForce the code is nearly the same, the only difference is to add the `Slicker` prefix, so instead of `Formatters.abc` we need to use `Slicker.Formatters.abc`

```ts
// ... SF_Slickgrid import


export class Example {
const Slicker = window.Slicker;

columnDefinitions: Column[];
gridOptions: GridOption;
dataset: any[];

constructor() {
// define the grid options & columns and then create the grid itself
this.defineGrid();
}

defineGrid() {
this.columnDefinitions = [
{ id: 'title', name: 'Title', field: 'title' },
{ id: 'duration', name: 'Duration (days)', field: 'duration' },
{ id: '%', name: '% Complete', field: 'percentComplete', formatter: Slicker.Formatters.percentComplete },
{ id: 'start', name: 'Start', field: 'start', formatter: Slicker.Formatters.dateIso },
{ id: 'finish', name: 'Finish', field: 'finish', formatter: Slicker.Formatters.dateIso },
{ id: 'effort-driven', name: 'Effort Driven', field: 'effortDriven', formatter: Slicker.Formatters.checkmarkMaterial }
];
}
}
```

### Extra Arguments/Params
What if you want to pass extra arguments that you want to use within the Formatter? You should use `params` for that. For example, let say you have a custom formatter to build a select list (dropdown), you could do it this way:
```ts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
- See the [Editors - Wiki](../Editors.md) for more general info about Editors (validators, event handlers, ...)

### Information
The Date Editor is provided through an external library named [Vanilla-Calendar-Picker](https://github.com/ghiscoding/vanilla-calendar-picker) (a fork of [Vanilla-Calendar-Pro](https://vanilla-calendar.pro)) and all options from that library can be added to your `editorOptions` (see below), so in order to add things like minimum date, disabling dates, ... just review all the [Vanilla-Calendar-Pro](https://vanilla-calendar.pro/docs/reference/additionally/settings) and then add them into `editorOptions`. Also just so you know, `editorOptions` is use by all other editors as well to expose external library like Autocompleter, Multiple-Select, etc...
The Date Editor is provided through an external library named [Vanilla-Calendar-Picker](https://github.com/ghiscoding/vanilla-calendar-picker) (a fork of [Vanilla-Calendar-Pro](https://vanilla-calendar.pro)) and all options from that library can be added to your `editorOptions` (see below), so in order to add things like minimum date, disabling dates, ... just review all the [Vanilla-Calendar-Pro](https://vanilla-calendar.pro/docs/reference/additionally/settings) and then add them into `editorOptions`. We use [Tempo](https://tempo.formkit.com/) to parse and format Dates to the chosen format (when `type`, `outputType` and/or `saveType` are provided in your column definition)

> **Note** Also just so you know, `editorOptions` is used by all other editors as well to expose external library like Autocompleter, Multiple-Select, etc...

### Demo
[Demo Page](https://ghiscoding.github.io/slickgrid-universal/#/example12) | [Demo Component](https://github.com/ghiscoding/slickgrid-universal/blob/master/examples/webpack-demo-vanilla-bundle/src/examples/example12.ts)
Expand Down
4 changes: 3 additions & 1 deletion docs/column-functionalities/filters/Compound-Filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ The column definition `type` will affect the list of Operators shown, for exampl


### How to use CompoundDate Filter
Again set the column definition flag `filterable: true` and use the filter type `Filters.compoundDate`. Here is an example with a full column definition:
As any other columns, set the column definition flag `filterable: true` and use the filter type `Filters.compoundDate`. Here is an example with a full column definition:
```ts
// define you columns, in this demo Effort Driven will use a Select Filter
this.columnDefinitions = [
Expand All @@ -75,6 +75,8 @@ this.gridOptions = {
};
```

> **Note** we use [Tempo](https://tempo.formkit.com/) to parse and format Dates to the chosen format via the `type` option when provided in your column definition.

#### Dealing with different input/ouput dates (example: UTC)
What if your date input (from your dataset) has a different output on the screen (UI)?
In that case, you will most probably have a Formatter and type representing the input type, we also provided an `outputType` that can be used to deal with that case.
Expand Down
2 changes: 2 additions & 0 deletions docs/column-functionalities/filters/Range-Filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ this.gridOptions = {
### Using a Date Range Filter
The date range filter allows you to search data between 2 dates (it uses [Vanilla-Calendar Range](https://vanilla-calendar.pro/) feature).

> **Note** we use [Tempo](https://tempo.formkit.com/) to parse and format Dates to the chosen format via the `type` option when provided in your column definition.

##### Component
import { Filters, Formatters, GridOption, OperatorType, VanillaCalendarOption } from '@slickgrid-universal/common';

Expand Down
2 changes: 1 addition & 1 deletion docs/getting-started/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ To get started follow any of these instruction Wikis depending on your choice of
| Angular | [Wiki - HOWTO (Step by Step)](https://ghiscoding.gitbook.io/angular-slickgrid/getting-started/quick-start) | [Live Demo](https://ghiscoding.github.io/Angular-Slickgrid/) |
| Aurelia | [Wiki - HOWTO (Step by Step)](https://ghiscoding.gitbook.io/aurelia-slickgrid/getting-started/quick-start) | [Live Demo](https://ghiscoding.github.io/aurelia-slickgrid/) |
| React | [Wiki - HOWTO (Step by Step)](https://ghiscoding.gitbook.io/slickgrid-react/getting-started/quick-start) | [Live Demo](https://ghiscoding.github.io/slickgrid-react/) |
| Salesforce | Installation | [Print Screen](https://github.com/ghiscoding/slickgrid-universal/wiki#salesforce-demo---print-screen) |
| Salesforce | [Salesforce Installation](getting-started/installation-salesforce.md) | [Print Screen](https://github.com/ghiscoding/slickgrid-universal/wiki#salesforce-demo---print-screen) |
| ---- | | |

**General Subjects**
Expand Down
10 changes: 9 additions & 1 deletion docs/migrations/migration-to-5.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ The goal of this new release was mainly to improve UI/UX (mostly for Dark Mode)
- Bootstrap >=v5.x (or any other UI framework)
- SASS >=v1.35 (`dart-sass`)
- migrated from Flatpickr to Vanilla-Calendar (visit [Vanilla-Calendar-Pro](https://vanilla-calendar.pro/) for demos and docs)
- migrated from MomentJS to [Tempo](https://tempo.formkit.com/) (by the FormKit
team)

> **Note** for the entire list of tasks & code changes applied in this release, you may want to take a look at the [Roadmap to 5.0](https://github.com/ghiscoding/slickgrid-universal/discussions/1482) Discussion.

Expand Down Expand Up @@ -228,6 +230,7 @@ if you want to read the Editor class (e.g. `Editors.longText`), you can now refe

## Grid Functionalities

### Sanitizer (DOMPurify)
`DOMPurify` is now completely optional via the `sanitizer` grid option and you must now provide it yourself. The main reason to make it optional was because most users would use `dompurify` but some users who require SSR support would want to use `isomorphic-dompurify`. You could also skip the `sanitizer` configuration, but that is not recommended.

> **Note** even if the `sanitizer` is optional, we **strongly suggest** that you configure it as a global grid option to avoid possible XSS attacks from your data and also to be CSP compliant. Note that for Salesforce users, you do not have to configure it since Salesforce already use DOMPurify internally.
Expand All @@ -239,4 +242,9 @@ this.gridOptions = {
};
```

> **Note** If you're wondering about the `ADD_ATTR: ['level']`, well the "level" is a custom attribute used by SlickGrid Grouping/Draggable Grouping to track the grouping level depth and it must be kept.
> **Note** If you're wondering about the `ADD_ATTR: ['level']`, well the "level" is a custom attribute used by SlickGrid Grouping/Draggable Grouping to track the grouping level depth and it must be kept.

### From MomentJS to Tempo
I wanted to replace MomentJS for a long time now (it's been deprecated for years and is CJS only), but it was really hard to find a good replacement (I tried DayJS, Luxon, date-fns and they all had problems)... and here comes [Tempo](https://tempo.formkit.com/)! With Tempo, I was finally able to migrate by taking advantage of `parse()` and `format()` Tempo functions which are the most important for our use case. The library also has plenty of extra optional functions as well, like `addDay()`, `diffDays()`, ... Another great thing about Tempo is that they use the same format [tokens](https://tempo.formkit.com/#format-tokens) as MomentJS, so the conversion on that side was super easy.

This migration should be transparent to most users like you, however if you were using MomentJS then I would suggest to consider trying [Tempo](https://tempo.formkit.com/) in your project in order to modernize your project and also lower your dependencies count. The other great advantage of Tempo is that it's ESM and it helps a lot in decreasing our build size footprint because of ESM Tree Shacking feature.
2 changes: 1 addition & 1 deletion examples/vite-demo-vanilla-bundle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"dependencies": {
"@faker-js/faker": "^8.4.1",
"@fnando/sparkline": "^0.3.10",
"@formkit/tempo": "^0.1.1",
"@slickgrid-universal/binding": "workspace:~",
"@slickgrid-universal/common": "workspace:~",
"@slickgrid-universal/composite-editor-component": "workspace:~",
Expand All @@ -27,7 +28,6 @@
"bulma": "^1.0.0",
"dompurify": "^3.1.2",
"fetch-jsonp": "^1.3.0",
"moment-tiny": "^2.30.4",
"multiple-select-vanilla": "^3.1.3",
"rxjs": "^7.8.1",
"vanilla-calendar-picker": "^2.11.4",
Expand Down
14 changes: 7 additions & 7 deletions examples/vite-demo-vanilla-bundle/src/examples/example10.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import {
import { BindingEventService } from '@slickgrid-universal/binding';
import { GraphqlService, type GraphqlPaginatedResult, type GraphqlServiceApi, type GraphqlServiceOption, } from '@slickgrid-universal/graphql';
import { Slicker, type SlickVanillaGridBundle } from '@slickgrid-universal/vanilla-bundle';
import { addDay, format } from '@formkit/tempo';
import { type MultipleSelectOption } from 'multiple-select-vanilla';
import moment from 'moment-tiny';

import { ExampleGridOptions } from './example-grid-options';
import type { TranslateService } from '../translate.service';
Expand Down Expand Up @@ -130,8 +130,8 @@ export default class Example10 {
},
];

const presetLowestDay = moment().add(-2, 'days').format('YYYY-MM-DD');
const presetHighestDay = moment().add(20, 'days').format('YYYY-MM-DD');
const presetLowestDay = format(addDay(new Date(), -2), 'YYYY-MM-DD');
const presetHighestDay = format(addDay(new Date(), 20), 'YYYY-MM-DD');

this.gridOptions = {
enableAutoTooltip: true,
Expand Down Expand Up @@ -303,8 +303,8 @@ export default class Example10 {
}

setFiltersDynamically() {
const presetLowestDay = moment().add(-2, 'days').format('YYYY-MM-DD');
const presetHighestDay = moment().add(20, 'days').format('YYYY-MM-DD');
const presetLowestDay = format(addDay(new Date(), -2), 'YYYY-MM-DD');
const presetHighestDay = format(addDay(new Date(), 20), 'YYYY-MM-DD');

// we can Set Filters Dynamically (or different filters) afterward through the FilterService
this.sgb.filterService.updateFilters([
Expand All @@ -325,8 +325,8 @@ export default class Example10 {
}

resetToOriginalPresets() {
const presetLowestDay = moment().add(-2, 'days').format('YYYY-MM-DD');
const presetHighestDay = moment().add(20, 'days').format('YYYY-MM-DD');
const presetLowestDay = format(addDay(new Date(), -2), 'YYYY-MM-DD');
const presetHighestDay = format(addDay(new Date(), 20), 'YYYY-MM-DD');

this.sgb?.filterService.updateFilters([
// you can use OperatorType or type them as string, e.g.: operator: 'EQ'
Expand Down
3 changes: 1 addition & 2 deletions examples/vite-demo-vanilla-bundle/src/examples/example11.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import { SlickCustomTooltip } from '@slickgrid-universal/custom-tooltip-plugin';
import { ExcelExportService } from '@slickgrid-universal/excel-export';
import { Slicker, type SlickVanillaGridBundle } from '@slickgrid-universal/vanilla-bundle';
import { type MultipleSelectOption } from 'multiple-select-vanilla';
import moment from 'moment-tiny';

import exampleModal from './example11-modal.html?raw';
import Example11Modal from './example11-modal';
Expand Down Expand Up @@ -82,7 +81,7 @@ export default class Example11 {
sgb: SlickVanillaGridBundle;
gridContainerElm: HTMLDivElement;
viewSelectElm: HTMLSelectElement;
currentYear = moment().year();
currentYear = new Date().getFullYear();
defaultPredefinedPresets = [
{
label: 'Tasks Finished in Previous Years (wo/Product,Country)',
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"@4tw/cypress-drag-drop": "^2.2.5",
"@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2",
"@formkit/tempo": "^0.1.1",
"@jest/types": "^29.6.3",
"@lerna-lite/cli": "^3.3.3",
"@lerna-lite/publish": "^3.3.3",
Expand All @@ -81,7 +82,6 @@
"jest-extended": "^4.0.2",
"jsdom": "^24.0.0",
"jsdom-global": "^3.0.2",
"moment-tiny": "^2.30.4",
"npm-run-all2": "^6.1.2",
"pnpm": "^8.15.8",
"rimraf": "^5.0.5",
Expand Down
2 changes: 1 addition & 1 deletion packages/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"not dead"
],
"dependencies": {
"@formkit/tempo": "^0.1.1",
"@slickgrid-universal/binding": "workspace:~",
"@slickgrid-universal/event-pub-sub": "workspace:~",
"@slickgrid-universal/utils": "workspace:~",
Expand All @@ -74,7 +75,6 @@
"autocompleter": "^9.2.1",
"dequal": "^2.0.3",
"excel-builder-vanilla": "3.0.1",
"moment-tiny": "^2.30.4",
"multiple-select-vanilla": "^3.1.3",
"sortablejs": "^1.15.2",
"un-flatten-tree": "^2.0.12",
Expand Down
31 changes: 17 additions & 14 deletions packages/common/src/commonEditorFilter/commonEditorFilterUtils.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { format } from '@formkit/tempo';
import type { AutocompleteItem } from 'autocompleter';
import type { IOptions } from 'vanilla-calendar-picker';
import moment from 'moment-tiny';

import type { AutocompleterOption, Column, ColumnEditor, ColumnFilter } from '../interfaces/index';
import { formatDateByFieldType, mapMomentDateFormatWithFieldType } from '../services';
import { FieldType } from '../enums';
import { formatDateByFieldType, mapTempoDateFormatWithFieldType, tryParseDate } from '../services/dateUtils';

/**
* add loading class ".slick-autocomplete-loading" to the Kraaden Autocomplete input element
Expand Down Expand Up @@ -37,23 +37,26 @@ export function setPickerDates(dateInputElm: HTMLInputElement, pickerOptions: IO
const currentDateOrDates = dateValues;
const outputFieldType = columnDef.outputType || colEditorOrFilter.type || columnDef.type || FieldType.dateUtc;
const inputFieldType = colEditorOrFilter.type || columnDef.type;
const isoFormat = mapMomentDateFormatWithFieldType(FieldType.dateIso) as string;
const inputFormat = inputFieldType ? mapMomentDateFormatWithFieldType(inputFieldType) : '';
const isoFormat = mapTempoDateFormatWithFieldType(FieldType.dateIso) as string;
const inputFormat = inputFieldType ? mapTempoDateFormatWithFieldType(inputFieldType) : undefined;
const initialDates = Array.isArray(currentDateOrDates) ? currentDateOrDates : [(currentDateOrDates || '') as string];
if (initialDates.length && initialDates[0]) {
const pickerDates = [];
const pickerDates: Date[] = [];
for (const initialDate of initialDates) {
const momentDate = moment(initialDate, inputFormat);
pickerDates.push(momentDate);
const date = initialDate instanceof Date ? initialDate : tryParseDate(initialDate, inputFormat);
if (date) {
pickerDates.push(date);
}
}

const singleinputFormat = Array.isArray(inputFormat) ? inputFormat[0] : inputFormat;
pickerOptions.settings!.selected = {
dates: [pickerDates.map(p => p.format(isoFormat)).join(':')],
month: pickerDates[0].month(),
year: pickerDates[0].year(),
time: singleinputFormat.toLowerCase().includes('h') ? pickerDates[0].format('HH:mm') : undefined,
};
if (pickerDates.length) {
pickerOptions.settings!.selected = {
dates: [pickerDates.map(p => format(p, isoFormat)).join(':')],
month: pickerDates[0].getMonth(),
year: pickerDates[0].getFullYear(),
time: inputFormat === 'ISO8601' || (inputFormat || '').toLowerCase().includes('h') ? format(pickerDates[0], 'HH:mm') : undefined,
};
}
dateInputElm.value = initialDates.length ? pickerDates.map(p => formatDateByFieldType(p, undefined, outputFieldType)).join(' — ') : '';
}
}
Loading
Loading