keystone-5 icon indicating copy to clipboard operation
keystone-5 copied to clipboard

CalendarDay field is causing reload (refresh) of the whole page after clicking on "next month" arrow

Open Yair-Ohana opened this issue 4 years ago • 2 comments

Describe the bug

basically, when clicking on the next/previous month buttons (image attached) reload is triggered (?!). The weird part is that it only happens on production, not locally.

To Reproduce

  1. Be sure to configure a CalendarDay field.
  2. Go to the Admin UI.
  3. Click on the next/previous month arrow.

Expected behavior

Clicking on one of the arrows will trigger an event that moving to the next/previous month.

Screenshots

image

System information

Happens on chrome. Using "@keystonejs/fields": "21.0.0",

Huge thanks.

Yair-Ohana avatar Apr 13 '21 05:04 Yair-Ohana

It looks like there hasn't been any activity here in over 6 months. Sorry about that! We've flagged this issue for special attention. It wil be manually reviewed by maintainers, not automatically closed. If you have any additional information please leave us a comment. It really helps! Thank you for you contribution. :)

stale[bot] avatar Sep 11 '21 00:09 stale[bot]

Reading the source code and managed to replicate the element but solving the error. I have solved I am using a custom input, to correct the refresh of the page when I change the month.

In any folder you want in my case server create a call CustomFields.

There I create a folder called CalendarDay with 3 files.

  • Field.js
  • Implementation.js
  • index.js

Field.js

/** @jsx jsx */
/* eslint-disable react/react-in-jsx-scope, jsx-a11y/no-autofocus */
import { jsx } from '@emotion/core';
import 'react-day-picker/dist/style.css';
import { DayPicker } from "react-day-picker";
import { Input } from '@arch-ui/input';
import { Alert } from '@arch-ui/alert';
import { FieldContainer, FieldLabel, FieldDescription, FieldInput } from '@arch-ui/fields';
import { parseISO, compareAsc, formatISO, isValid } from 'date-fns';

const CalendarDayField = ({ autoFocus, field, value, errors, onChange, isDisabled }) => {
	const htmlID = `ks-daypicker-${field.path}`;
	const handleDayClick = day => onChange(formatISO(day, { representation: 'date' }));

	return (
		<FieldContainer>
			<FieldLabel htmlFor={htmlID} field={field} errors={errors} />
			<FieldDescription text={field.adminDoc} />
			<FieldInput>
				<DayPicker
					disabled={[
						day =>
							isDisabled ||
							(field.config.dateTo && compareAsc(day, parseISO(field.config.dateTo)) === 1) ||
							(field.config.dateTo && compareAsc(parseISO(field.config.dateFrom), day) === 1),
					]}
					selected={isValid(parseISO(value)) ? parseISO(value) : undefined}
					defaultMonth={isValid(parseISO(value)) ? parseISO(value) : undefined}
					onDayClick={handleDayClick}
				/>
			</FieldInput>

			<FieldInput>
				<Input
					id={htmlID}
					autoFocus={autoFocus}
					onKeyDown={e => {
						// There is a strange bug where after interacting with the day picker
						// and then pressing enter on the input the value is changed to the start
						// of the month. I think this is bug with the day picker.
						// The following is a work-around:
						if (e.key === 'Enter') {
							e.preventDefault();
						}
					}}
					onChange={e => {
						// Tiny bit of date format normalisation for convenience
						const normalisedValue = e.target.value.replace('/', '-').replace('\\', '-');
						const parsedValue = parseISO(normalisedValue);
						if (normalisedValue.length === 10 && isValid(parsedValue)) {
							handleDayClick(parsedValue);
						} else {
							onChange(normalisedValue);
						}
					}}
					disabled={isDisabled}
					css={{ color: isValid(parseISO(value)) ? undefined : 'darkred' }}
					value={value}
				/>
			</FieldInput>

			{errors.map(({ message, data }) => (
				<Alert appearance="danger" key={message}>
					{message}
					{data ? ` - ${JSON.stringify(data)}` : null}
				</Alert>
			))}
		</FieldContainer>
	);
};

export default CalendarDayField;

Implementation.js

const { CalendarDay } = require('@keystonejs/fields');

// Using the text implementation because we're going to stringify the array of results.
// We could store this in another table, but this would require writing a complex controller.
// JSON.stringify feels good enough for this simple field.

module.exports = {
	Implementation: CalendarDay.implementation,
	MongoIntegerInterface: CalendarDay.adapters.mongoose,
	KnexIntegerInterface: CalendarDay.adapters.knex,
};

index.js

const { Implementation, MongoIntegerInterface, KnexIntegerInterface } = require('./Implementation');

module.exports = {
	type: 'CustomCalendarDay',
	implementation: Implementation,
	views: {
		Controller: require.resolve('@keystonejs/fields/types/CalendarDay/views/Controller/dist/fields.cjs'),
		Field: require.resolve('./Field'),
		Filter: require.resolve('@keystonejs/fields/types/CalendarDay/views/Filter/dist/fields.cjs'),
		Cell: require.resolve('@keystonejs/fields/types/CalendarDay/views/Cell/dist/fields.cjs'),
	},
	adapters: {
		mongoose: MongoIntegerInterface,
		knex: KnexIntegerInterface,
	},
};

Now use in Models

const CalendarDay = require('../server/CustomField/CalendarDay')

module.exports = {
	fields: {
		date: {
		    type: CalendarDay
		}
	}
};

NOTE: Install "react-day-picker": "8.0.0-beta.37" from npm install [email protected]

Brandyweb avatar Apr 14 '22 01:04 Brandyweb