Skip to content

Commit

Permalink
Add dateFrom, dateTo validation to CalendarDay
Browse files Browse the repository at this point in the history
  • Loading branch information
timleslie committed May 26, 2020
1 parent a520364 commit 3dbd671
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 29 deletions.
4 changes: 2 additions & 2 deletions demo-projects/blog/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ exports.User = {
dob: {
type: CalendarDay,
format: 'do MMMM yyyy',
yearRangeFrom: 1901,
yearRangeTo: getYear(new Date()),
dateFrom: '1901-01-01',
dateTo: getYear(new Date()), // FIXME
},
...(process.env.IFRAMELY_API_KEY
? {
Expand Down
3 changes: 2 additions & 1 deletion demo-projects/todo/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { Keystone } = require('@keystonejs/keystone');
const { MongooseAdapter } = require('@keystonejs/adapter-mongoose');
const { Text } = require('@keystonejs/fields');
const { Text, CalendarDay } = require('@keystonejs/fields');
const { GraphQLApp } = require('@keystonejs/app-graphql');
const { AdminUIApp } = require('@keystonejs/app-admin-ui');
const { StaticApp } = require('@keystonejs/app-static');
Expand All @@ -14,6 +14,7 @@ keystone.createList('Todo', {
schemaDoc: 'A list of things which need to be done',
fields: {
name: { type: Text, schemaDoc: 'This is the thing you need to do', isRequired: true },
day: { type: CalendarDay, dateTo: '2000-01-01', dateFrom: '2000-01-01' },
},
});

Expand Down
59 changes: 46 additions & 13 deletions packages/fields/src/types/CalendarDay/Implementation.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
import { formatISO, parseISO } from 'date-fns';
import { formatISO, parseISO, compareAsc, compareDesc, isValid } from 'date-fns';
import { Implementation } from '../../Implementation';
import { MongooseFieldAdapter } from '@keystonejs/adapter-mongoose';
import { KnexFieldAdapter } from '@keystonejs/adapter-knex';

export class CalendarDay extends Implementation {
constructor(
path,
{
format = 'yyyy-MM-dd',
yearRangeFrom = new Date().getFullYear() - 100,
yearRangeTo = new Date().getFullYear(),
}
) {
constructor(path, { format = 'yyyy-MM-dd', dateFrom, dateTo }) {
super(...arguments);
this.format = format;
this.yearRangeFrom = yearRangeFrom;
this.yearRangeTo = yearRangeTo;
this._dateFromString = dateFrom;
this._dateToString = dateTo;
this._dateFromJS = dateFrom && parseISO(dateFrom);
this._dateToJS = dateTo && parseISO(dateTo);

if (dateFrom && !isValid(this._dateFromJS)) {
throw new Error(
`Invalid value for option "dateFrom" of field '${this.listKey}.${path}': "${dateFrom}"`
);
}
if (dateTo && !isValid(this._dateToJS)) {
throw new Error(
`Invalid value for option "dateTo" of field '${this.listKey}.${path}': "${dateTo}"`
);
}

if (dateTo && dateFrom && compareAsc(this._dateFromJS, this._dateToJS) === 1) {
throw new Error(
`Invalid values for options "dateFrom", "dateTo" of field '${this.listKey}.${path}': "${dateFrom}" > "${dateTo}"`
);
}
this.isOrderable = true;
}

Expand Down Expand Up @@ -43,10 +55,31 @@ export class CalendarDay extends Implementation {
return {
...meta,
format: this.format,
yearRangeFrom: this.yearRangeFrom,
yearRangeTo: this.yearRangeTo,
dateFrom: this.dateFrom,
dateTo: this.dateTo,
};
}

async validateInput({ resolvedData, addFieldValidationError }) {
const parsedValue = resolvedData[this.path] && parseISO(resolvedData[this.path]);
if (!isValid(parsedValue)) {
addFieldValidationError('Invalid CalendarDay value', { value: resolvedData[this.path] });
}
if (parsedValue) {
if (this._dateFromJS && compareAsc(this._dateFromJS, parsedValue) === 1) {
addFieldValidationError('Value is before earliest allowed date.', {
value: resolvedData[this.path],
dateFrom: this._dateFromString,
});
}
if (this._dateToJS && compareDesc(this._dateToJS, parsedValue) === 1) {
addFieldValidationError('Value is after latest allowed date.', {
value: resolvedData[this.path],
dateTo: this._dateToString,
});
}
}
}
}

const CommonCalendarInterface = superclass =>
Expand Down
11 changes: 0 additions & 11 deletions packages/fields/src/types/CalendarDay/views/Controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,4 @@ export default class CalendarDayController extends FieldController {
// QUESTION: should we support "in" and "not_in" filters for DateTime?
// What does the UI look like for that.
];

validateInput = ({ resolvedData, addFieldValidationError }) => {
const { yearRangeFrom, yearRangeTo } = this.config;

const inputYear = getYear(parseISO(resolvedData[this.path]));
const inRange = yearRangeFrom <= inputYear && inputYear <= yearRangeTo;

if (!inRange) {
return addFieldValidationError(`Input not within configured date interval.`);
}
};
}
4 changes: 2 additions & 2 deletions test-projects/basic/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ keystone.createList('User', {
dob: {
type: CalendarDay,
format: 'do MMMM yyyy',
yearRangeFrom: 1901,
yearRangeTo: getYear(new Date()),
dateFrom: '1901-01-01',
dateTo: getYear(new Date()), // FIXME
},
lastOnline: {
type: DateTime,
Expand Down

0 comments on commit 3dbd671

Please sign in to comment.