From f0c741e27ce1f43dc523dc4bda64ac4e9e1bd41d Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Tue, 28 Nov 2023 01:52:01 -0500 Subject: [PATCH] feat(Formatters): add new `Formatters.iconBoolean` for icon w/truthy val - this formatter is meant to be generic to display any icon you want on a boolean truthy value. It was created to replace the `Formatters.checkmark` which is only working for users with Font-Awesome 4 and nothing else, basically this new formatter is a lot less restrictive and allows the user to use any CSS class name he wants to use. --- .../__tests__/iconBooleanFormatter.spec.ts | 116 ++++++++++++++++++ .../common/src/formatters/formatters.index.ts | 7 ++ .../src/formatters/iconBooleanFormatter.ts | 19 +++ packages/common/src/formatters/index.ts | 1 + 4 files changed, 143 insertions(+) create mode 100644 packages/common/src/formatters/__tests__/iconBooleanFormatter.spec.ts create mode 100644 packages/common/src/formatters/iconBooleanFormatter.ts diff --git a/packages/common/src/formatters/__tests__/iconBooleanFormatter.spec.ts b/packages/common/src/formatters/__tests__/iconBooleanFormatter.spec.ts new file mode 100644 index 000000000..be6284fcd --- /dev/null +++ b/packages/common/src/formatters/__tests__/iconBooleanFormatter.spec.ts @@ -0,0 +1,116 @@ +import { Column } from '../../interfaces/index'; +import { iconBooleanFormatter } from '../iconBooleanFormatter'; + +describe('the Checkmark Formatter', () => { + it('should throw an error when omitting to pass "params.cssClass"', () => { + expect(() => iconBooleanFormatter(0, 0, 'anything', {} as Column, {}, {} as any)) + .toThrow('Slickgrid-Universal] When using `Formatters.iconBoolean`, you must provide You must provide the "cssClass"'); + }); + + it('should return an empty string when no value is passed', () => { + const value = null; + const cssClass = 'fa fa-check'; + const result = iconBooleanFormatter(0, 0, value, { field: 'user', params: { cssClass } } as Column, {}, {} as any); + expect(result).toBe(''); + }); + + it('should return an empty string when False is provided', () => { + const value = false; + const cssClass = 'fa fa-check'; + const result = iconBooleanFormatter(0, 0, value, { field: 'user', params: { cssClass } } as Column, {}, {} as any); + expect(result).toBe(''); + }); + + it('should return an empty string when the string "FALSE" (case insensitive) is provided', () => { + const value = 'FALSE'; + const cssClass = 'fa fa-check'; + const result1 = iconBooleanFormatter(0, 0, value.toLowerCase(), { field: 'user', params: { cssClass } } as Column, {}, {} as any); + const result2 = iconBooleanFormatter(0, 0, value.toUpperCase(), { field: 'user', params: { cssClass } } as Column, {}, {} as any); + expect(result1).toBe(''); + expect(result2).toBe(''); + }); + + it('should return the Font Awesome Checkmark icon when the string "True" (case insensitive) is provided', () => { + const value = 'True'; + const cssClass = 'fa fa-check'; + const result1 = iconBooleanFormatter(0, 0, value.toLowerCase(), { field: 'user', params: { cssClass } } as Column, {}, {} as any); + const result2 = iconBooleanFormatter(0, 0, value.toUpperCase(), { field: 'user', params: { cssClass } } as Column, {}, {} as any); + expect(result1).toBe(''); + expect(result2).toBe(''); + }); + + it('should return the Font Awesome Checkmark icon when input is True', () => { + const value = true; + const cssClass = 'fa fa-check'; + const result = iconBooleanFormatter(0, 0, value, { field: 'user', params: { cssClass } } as Column, {}, {} as any); + expect(result).toBe(''); + }); + + it('should return the Font Awesome Checkmark icon when input is a string even if it start with 0', () => { + const value = '005A00ABC'; + const cssClass = 'fa fa-check'; + const result1 = iconBooleanFormatter(0, 0, value, { field: 'user', params: { cssClass } } as Column, {}, {} as any); + expect(result1).toBe(''); + }); + + it('should return an empty string when the string "0" is provided', () => { + const value = '0'; + const cssClass = 'fa fa-check'; + const result = iconBooleanFormatter(0, 0, value, { field: 'user', params: { cssClass } } as Column, {}, {} as any); + expect(result).toBe(''); + }); + + it('should return the Font Awesome Checkmark icon when input is a number greater than 0', () => { + const value = 0.000001; + const cssClass = 'fa fa-check'; + const result1 = iconBooleanFormatter(0, 0, value, { field: 'user', params: { cssClass } } as Column, {}, {} as any); + expect(result1).toBe(''); + }); + + it('should return the Font Awesome Checkmark icon when input is a number as a text greater than 0', () => { + const value = '0.000001'; + const cssClass = 'fa fa-check'; + const result1 = iconBooleanFormatter(0, 0, value, { field: 'user', params: { cssClass } } as Column, {}, {} as any); + expect(result1).toBe(''); + }); + + it('should return an empty string when input is a number lower or equal to 0', () => { + const value1 = 0; + const value2 = -0.5; + const cssClass = 'fa fa-check'; + const result1 = iconBooleanFormatter(0, 0, value1, { field: 'user', params: { cssClass } } as Column, {}, {} as any); + const result2 = iconBooleanFormatter(0, 0, value2, { field: 'user', params: { cssClass } } as Column, {}, {} as any); + expect(result1).toBe(''); + expect(result2).toBe(''); + }); + + it('should return an empty string when input is a number as a text and lower or equal to 0', () => { + const value1 = '0'; + const value2 = '-0.5'; + const cssClass = 'fa fa-check'; + const result1 = iconBooleanFormatter(0, 0, value1, { field: 'user', params: { cssClass } } as Column, {}, {} as any); + const result2 = iconBooleanFormatter(0, 0, value2, { field: 'user', params: { cssClass } } as Column, {}, {} as any); + expect(result1).toBe(''); + expect(result2).toBe(''); + }); + + it('should return an empty string when input is type null or undefined', () => { + const value1 = null; + const value2 = undefined; + const cssClass = 'fa fa-check'; + const result1 = iconBooleanFormatter(0, 0, value1, { field: 'user', params: { cssClass } } as Column, {}, {} as any); + const result2 = iconBooleanFormatter(0, 0, value2, { field: 'user', params: { cssClass } } as Column, {}, {} as any); + expect(result1).toBe(''); + expect(result2).toBe(''); + }); + + it('should return the Font Awesome Checkmark icon when input is the "null" or "undefined"', () => { + const value1 = 'null'; + const value2 = 'undefined'; + const cssClass = 'fa fa-check'; + const result1 = iconBooleanFormatter(0, 0, value1, { field: 'user', params: { cssClass } } as Column, {}, {} as any); + const result2 = iconBooleanFormatter(0, 0, value2, { field: 'user', params: { cssClass } } as Column, {}, {} as any); + expect(result1).toBe(''); + expect(result2).toBe(''); + }); +}); diff --git a/packages/common/src/formatters/formatters.index.ts b/packages/common/src/formatters/formatters.index.ts index e1e3f865a..1df6f7f50 100644 --- a/packages/common/src/formatters/formatters.index.ts +++ b/packages/common/src/formatters/formatters.index.ts @@ -20,6 +20,7 @@ import { dollarFormatter } from './dollarFormatter'; import { editIconFormatter } from './editIconFormatter'; import { fakeHyperlinkFormatter } from './fakeHyperlinkFormatter'; import { hyperlinkFormatter } from './hyperlinkFormatter'; +import { iconBooleanFormatter } from './iconBooleanFormatter'; import { iconFormatter } from './iconFormatter'; import { infoIconFormatter } from './infoIconFormatter'; import { italicFormatter } from './italicFormatter'; @@ -235,6 +236,12 @@ export const Formatters = { /** Display whichever icon you want (library agnostic, it could be Font-Awesome or any other) */ icon: iconFormatter, + /** + * Display whichever icon but only for boolean truthy values (library agnostic, it could be Font-Awesome or any other) + * Note: a value of "false", null, undefined, "1" or any number below 0 are all considered falsy and will not display the icon + */ + iconBoolean: iconBooleanFormatter, + /** @deprecated @use `Formatters.icon` instead. Displays a Font-Awesome edit icon (fa-info-circle) */ infoIcon: infoIconFormatter, diff --git a/packages/common/src/formatters/iconBooleanFormatter.ts b/packages/common/src/formatters/iconBooleanFormatter.ts new file mode 100644 index 000000000..4d69e016d --- /dev/null +++ b/packages/common/src/formatters/iconBooleanFormatter.ts @@ -0,0 +1,19 @@ +import { type Formatter } from './../interfaces/index'; + +/** Display whichever icon for a boolean value (library agnostic, it could be Font-Awesome or any other) */ +export const iconBooleanFormatter: Formatter = (_row, _cell, value, columnDef) => { + const columnParams = columnDef?.params || {}; + const cssClass = columnParams.cssClass; + + if (!cssClass) { + throw new Error('[Slickgrid-Universal] When using `Formatters.iconBoolean`, you must provide You must provide the "cssClass", e.g.: { formatter: Formatters.iconBoolean, params: { cssClass: "fa fa-check" }}'); + } + + let isTruthy = false; + const isNumber = !isNaN(value); + if (value === true || (isNumber && parseFloat(value) > 0) || (!isNumber && typeof value === 'string' && value.toLowerCase() !== 'false' && value !== '0')) { + isTruthy = true; + } + + return isTruthy ? `` : ''; +}; diff --git a/packages/common/src/formatters/index.ts b/packages/common/src/formatters/index.ts index 164eff73b..362236121 100644 --- a/packages/common/src/formatters/index.ts +++ b/packages/common/src/formatters/index.ts @@ -18,6 +18,7 @@ export * from './editIconFormatter'; export * from './formatters.index'; export * from './formatterUtilities'; export * from './hyperlinkFormatter'; +export * from './iconBooleanFormatter'; export * from './iconFormatter'; export * from './infoIconFormatter'; export * from './italicFormatter';