Skip to content

Commit

Permalink
feat(kit): Date add max/min options (#70)
Browse files Browse the repository at this point in the history
Co-authored-by: v.potekhin <v.potekhin@tinkoff.ru>
  • Loading branch information
vladimirpotekhin and v.potekhin authored Jan 23, 2023
1 parent 19fda20 commit b708243
Show file tree
Hide file tree
Showing 11 changed files with 352 additions and 1 deletion.
105 changes: 105 additions & 0 deletions projects/demo-integrations/cypress/tests/kit/date/date-min-max.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import {DemoPath} from '@demo/routes';

describe('Date', () => {
describe('Max date', () => {
beforeEach(() => {
cy.visit(`/${DemoPath.Date}/API?max=2020-05-05`);
cy.get('#demo-content input')
.should('be.visible')
.first()
.focus()
.as('input');
});

it('Input less than max value', () => {
cy.get('@input')
.type('31122019')
.should('have.value', '31.12.2019')
.should('have.prop', 'selectionStart', '31.12.2019'.length)
.should('have.prop', 'selectionEnd', '31.12.2019'.length);
});

it('05.12.202| => type 5 => 05.05.2020 (max value)', () => {
cy.get('@input')
.type('0512202')
.should('have.value', '05.12.202')
.should('have.prop', 'selectionStart', '05.12.202'.length)
.should('have.prop', 'selectionEnd', '05.12.202'.length)
.type('5')
.should('have.value', '05.05.2020')
.should('have.prop', 'selectionStart', '05.05.2020'.length)
.should('have.prop', 'selectionEnd', '05.05.2020'.length);
});

it('0|3.05.2020 => type 7 => 05|.05.2020 (max value)', () => {
cy.get('@input')
.type('03052020')
.type('{moveToStart}{rightArrow}')
.type('7')
.should('have.value', '05.05.2020')
.should('have.prop', 'selectionStart', '05.'.length)
.should('have.prop', 'selectionEnd', '05.'.length);
});

it('03.0|5.2020 => type 7 => 05.05|.2020 (max value)', () => {
cy.get('@input')
.type('03052020')
.type('{leftArrow}'.repeat('5.2020'.length))
.type('7')
.should('have.value', '05.05.2020')
.should('have.prop', 'selectionStart', '05.05.'.length)
.should('have.prop', 'selectionEnd', '05.05.'.length);
});
});

describe('Min date', () => {
beforeEach(() => {
cy.visit(`/${DemoPath.Date}/API?min=2020-05-05`);
cy.get('#demo-content input')
.should('be.visible')
.first()
.focus()
.as('input');
});

it('Input more than min value', () => {
cy.get('@input')
.type('20102022')
.should('have.value', '20.10.2022')
.should('have.prop', 'selectionStart', '20.10.2022'.length)
.should('have.prop', 'selectionEnd', '20.10.2022'.length);
});

it('05.12.201| => type 9 => 05.05.2020 (min value)', () => {
cy.get('@input')
.type('0512201')
.should('have.value', '05.12.201')
.should('have.prop', 'selectionStart', '05.12.201'.length)
.should('have.prop', 'selectionEnd', '05.12.201'.length)
.type('9')
.should('have.value', '05.05.2020')
.should('have.prop', 'selectionStart', '05.05.2020'.length)
.should('have.prop', 'selectionEnd', '05.05.2020'.length);
});

it('0|7.05.2020 => type 2 => 05|.05.2020 (min value)', () => {
cy.get('@input')
.type('07052020')
.type('{moveToStart}{rightArrow}')
.type('2')
.should('have.value', '05.05.2020')
.should('have.prop', 'selectionStart', '05.'.length)
.should('have.prop', 'selectionEnd', '05.'.length);
});

it('03.0|6.2020 => type 2 => 05.05|.2020 (min value)', () => {
cy.get('@input')
.type('03062020')
.type('{leftArrow}'.repeat('6.2020'.length))
.type('2')
.should('have.value', '05.05.2020')
.should('have.prop', 'selectionStart', '05.05.'.length)
.should('have.prop', 'selectionEnd', '05.05.'.length);
});
});
});
51 changes: 51 additions & 0 deletions projects/demo-integrations/cypress/tests/kit/date/date-mode.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {DemoPath} from '@demo/routes';

describe('Date', () => {
describe('Mode', () => {
describe('YMD', () => {
beforeEach(() => {
cy.visit(`/${DemoPath.Date}/API?mode=YMD`);
cy.get('#demo-content input')
.should('be.visible')
.first()
.focus()
.as('input');
});

it(' "YMD" => 2019.12.31', () => {
cy.get('@input')
.type('20193')
.should('have.value', '2019.03')
.should('have.prop', 'selectionStart', '2019.03'.length)
.should('have.prop', 'selectionEnd', '2019.03'.length)
.type('22')
.should('have.value', '2019.03.22')
.should('have.prop', 'selectionStart', '2019.03.22'.length)
.should('have.prop', 'selectionEnd', '2019.03.22'.length);
});
});

describe('MDY', () => {
beforeEach(() => {
cy.visit(`/${DemoPath.Date}/API?mode=MDY`);
cy.get('#demo-content input')
.should('be.visible')
.first()
.focus()
.as('input');
});

it(' "MDY" => 03.12.2020', () => {
cy.get('@input')
.type('312')
.should('have.value', '03.12')
.should('have.prop', 'selectionStart', '03.12'.length)
.should('have.prop', 'selectionEnd', '03.12'.length)
.type('2022')
.should('have.value', '03.12.2022')
.should('have.prop', 'selectionStart', '03.12.2022'.length)
.should('have.prop', 'selectionEnd', '03.12.2022'.length);
});
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {DemoPath} from '@demo/routes';

describe('Date', () => {
describe('Separator', () => {
describe('/', () => {
beforeEach(() => {
cy.visit(`/${DemoPath.Date}/API?separator=/`);
cy.get('#demo-content input')
.should('be.visible')
.first()
.focus()
.as('input');
});

it(' "/" => 31/12/2019', () => {
cy.get('@input')
.type('3112')
.should('have.value', '31/12')
.should('have.prop', 'selectionStart', '31/12'.length)
.should('have.prop', 'selectionEnd', '31/12'.length)
.type('2019')
.should('have.value', '31/12/2019')
.should('have.prop', 'selectionStart', '31/12/2019'.length)
.should('have.prop', 'selectionEnd', '31/12/2019'.length);
});
});

describe('-', () => {
beforeEach(() => {
cy.visit(`/${DemoPath.Date}/API?separator=-`);
cy.get('#demo-content input')
.should('be.visible')
.first()
.focus()
.as('input');
});

it(' "-" => 31-12-2019', () => {
cy.get('@input')
.type('3112')
.should('have.value', '31-12')
.should('have.prop', 'selectionStart', '31-12'.length)
.should('have.prop', 'selectionEnd', '31-12'.length)
.type('2019')
.should('have.value', '31-12-2019')
.should('have.prop', 'selectionStart', '31-12-2019'.length)
.should('have.prop', 'selectionEnd', '31-12-2019'.length);
});
});
});
});
19 changes: 19 additions & 0 deletions projects/demo/src/pages/kit/date/date-mask-doc.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,33 @@ export class DateMaskDocComponent implements GeneratorOptions {
YMD: maskitoDateOptionsGenerator({mode: 'YMD', separator: '/'}),
};

minMask = maskitoDateOptionsGenerator({mode: 'DMY', min: new Date(2010, 5, 1)});
minMaxMask = maskitoDateOptionsGenerator({
mode: 'DMY',
min: new Date(2000, 0, 1),
max: new Date(2025, 4, 10),
});

readonly modeOptions: MaskitoDateMode[] = [`DMY`, `MDY`, `YMD`];
readonly separatorOptions: string[] = [`.`, `/`, `-`];
readonly minMaxOptions = ['0001-01-01', '9999-12-31', '2000-01-01', '2025-05-10'];
minStr = this.minMaxOptions[0];
maxStr = this.minMaxOptions[1];

mode: MaskitoDateMode = this.modeOptions[0];
separator = this.separatorOptions[0];

min = new Date(this.minStr);
max = new Date(this.maxStr);

maskitoOptions: MaskitoOptions = maskitoDateOptionsGenerator(this);

updateDate(): void {
this.min = new Date(this.minStr);
this.max = new Date(this.maxStr);
this.updateOptions();
}

updateOptions(): void {
this.maskitoOptions = maskitoDateOptionsGenerator(this);
}
Expand Down
55 changes: 55 additions & 0 deletions projects/demo/src/pages/kit/date/date-mask-doc.template.html
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,41 @@
/>
</tui-input>
</tui-doc-example>

<tui-doc-example
id="min-max"
heading="Min/Max"
>
<span>Min 01.06.2010</span>
<tui-input
tuiTextfieldCustomContent="tuiIconCalendarLarge"
ngModel="02.06.2018"
tuiTextfieldFiller="dd.mm.yyyy"
class="input-date"
>
Date
<input
tuiTextfield
inputmode="decimal"
[maskito]="minMask"
/>
</tui-input>

<span>Min 01.01.2000, Max 10.05.2025</span>
<tui-input
tuiTextfieldCustomContent="tuiIconCalendarLarge"
ngModel="20.01.2023"
tuiTextfieldFiller="dd.mm.yyyy"
class="input-date"
>
Date
<input
tuiTextfield
inputmode="decimal"
[maskito]="minMaxMask"
/>
</tui-input>
</tui-doc-example>
</ng-template>

<ng-template pageTab>
Expand Down Expand Up @@ -141,6 +176,26 @@
>
Separator
</ng-template>
<ng-template
documentationPropertyName="min"
documentationPropertyMode="input"
documentationPropertyType="Date"
[documentationPropertyValues]="minMaxOptions"
[(documentationPropertyValue)]="minStr"
(documentationPropertyValueChange)="updateDate()"
>
Minimum date
</ng-template>
<ng-template
documentationPropertyName="max"
documentationPropertyMode="input"
documentationPropertyType="Date"
[documentationPropertyValues]="minMaxOptions"
[(documentationPropertyValue)]="maxStr"
(documentationPropertyValueChange)="updateDate()"
>
Maximum date
</ng-template>
</tui-doc-documentation>
</ng-template>
</tui-doc-page>
12 changes: 11 additions & 1 deletion projects/kit/src/lib/masks/date/date-mask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import {MaskitoOptions, maskitoPipe} from '@maskito/core';

import {createZeroPlaceholdersPreprocessor} from '../../processors';
import {DATE_SEGMENT_VALUE_LENGTH} from './constants';
import {createMaxValidationPreprocessor} from './processors';
import {
createMaxValidationPreprocessor,
createMinMaxValuePostprocessor,
} from './processors';
import {MaskitoDateMode} from './types';

const RepeatDataChars: Record<string, number> = {
Expand All @@ -14,9 +17,13 @@ const RepeatDataChars: Record<string, number> = {
export function maskitoDateOptionsGenerator({
mode,
separator = '.',
max,
min,
}: {
mode: MaskitoDateMode;
separator?: string;
max?: Date;
min?: Date;
}): MaskitoOptions {
const fullDateMode = Array.from(mode)
.join(separator)
Expand All @@ -31,5 +38,8 @@ export function maskitoDateOptionsGenerator({
createZeroPlaceholdersPreprocessor(),
createMaxValidationPreprocessor(fullDateMode, separator),
),
postprocessor: maskitoPipe(
createMinMaxValuePostprocessor({min, max}, fullDateMode),
),
};
}
1 change: 1 addition & 0 deletions projects/kit/src/lib/masks/date/processors/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './max-validation-preprocessor';
export * from './min-max-postprocessor';
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {MaskitoOptions} from '@maskito/core';

import {dateToSegments, parseDateString, segmentsToDate, toDateString} from '../utils';

export function createMinMaxValuePostprocessor(
{
min = new Date('0001-01-01'),
max = new Date('9999-12-31'),
}: {
min?: Date;
max?: Date;
},
fullDateMode: string,
): NonNullable<MaskitoOptions['postprocessor']> {
return elementState => {
const {value, selection} = elementState;

if (value.length < fullDateMode.length) {
return elementState;
}

const parsedDate = parseDateString(value, fullDateMode);
const date = segmentsToDate(parsedDate);

if (date < min || date > max) {
const finalValue = toDateString(
dateToSegments(date < min ? min : max),
fullDateMode,
);

return {
selection,
value: finalValue,
};
}

return elementState;
};
}
Loading

0 comments on commit b708243

Please sign in to comment.