Skip to content

Commit

Permalink
fix: now datepicker shows either date or datetime
Browse files Browse the repository at this point in the history
Before the change datepicker showed always datetime

fixes #463
  • Loading branch information
wojtek-krysiak committed Jul 25, 2020
1 parent ab1e4f8 commit 961d67d
Show file tree
Hide file tree
Showing 13 changed files with 179 additions and 37 deletions.
69 changes: 69 additions & 0 deletions example-app/cypress/integration/pages/create-page.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/// <reference types="cypress" />
/// <reference types="../../support" />

const dateRegex = /^[\d]{4}-[\d]{2}-[\d]{2}$/
const dateTimeRegex = /^[\d]{4}-[\d]{2}-[\d]{2} [\d]{2}:[\d]{2}$/

context('resources/Profession/actions/new', () => {
before(() => {
cy.login()
})

beforeEach(() => {
Cypress.Cookies.preserveOnce(Cypress.env('COOKIE_NAME'))
cy.visit('resources/Page/actions/new')
})

it('creates new page', () => {
const data = {
title: 'Some title',
content: 'hello world',
createdDate: '2011-01-01',
createdDateTime: '2011-01-01 11:00',
}

cy.get('[data-testid="property-edit-title"] input').type(data.title)
cy.get('[data-testid="property-edit-content"] .ql-editor')
.click()
.type(data.content)
cy.get('[data-testid="property-edit-createdDate"] input').type(data.createdDate)
cy.get('[class^="date-picker__Overlay"].visible').click()
cy.get('[data-testid="property-edit-createdDateTime"] input').type(data.createdDateTime)
cy.get('[class^="date-picker__Overlay"].visible').click()

cy.get('button[type=submit]').contains('Save').click()

cy.location('pathname').should('eq', '/admin/resources/Page')

cy.get('td[data-property-name="title"]')
.contains(data.title)
.parents('tr')
.then((parent) => {
expect(parent.find('[data-property-name="title"]')).to.have.text(data.title)
expect(parent.find('[data-property-name="content"]')).to.have.text(`<p>${data.content}<...`)
expect(parent.find('[data-property-name="createdDate"]').text()).to.match(dateRegex)
expect(parent.find('[data-property-name="createdDateTime"]').text()).to.match(dateTimeRegex)
})
})

it('shows regular date picker for date property', () => {
cy.get('[data-testid="property-edit-createdDate"] input').click()
cy.get('[data-testid="property-edit-createdDate"] .react-datepicker-time__input').should('not.exist')
cy.get('[data-testid="property-edit-createdDate"] .react-datepicker__day.react-datepicker__day--001')
.not('.react-datepicker__day--outside-month').click()
cy.get('[data-testid="property-edit-createdDate"] input').then(($el) => {
expect($el.val()).to.match(dateRegex)
})
})

it('shows datetime picker for date property', () => {
cy.get('[data-testid="property-edit-createdDateTime"] input').click()
cy.get('[data-testid="property-edit-createdDateTime"] .react-datepicker-time__input').should('exist')
cy.get('[data-testid="property-edit-createdDateTime"] .react-datepicker__day.react-datepicker__day--001')
.not('.react-datepicker__day--outside-month').click()

cy.get('[data-testid="property-edit-createdDateTime"] input').then(($el) => {
expect($el.val()).to.match(dateTimeRegex)
})
})
})
6 changes: 6 additions & 0 deletions example-app/src/pages/page.admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ const options = {
},
},
},
createdDate: {
type: 'date',
},
createdDateTime: {
type: 'datetime',
},
},
}

Expand Down
2 changes: 2 additions & 0 deletions example-app/src/pages/page.entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const PageSchema = new mongoose.Schema({
content: {
type: String,
},
createdDate: Date,
createdDateTime: Date,
})

const Page = mongoose.model('Page', PageSchema)
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
"@types/flat": "^0.0.28",
"@types/lodash": "^4.14.141",
"@types/mocha": "^5.2.7",
"@types/react-datepicker": "^3.1.0",
"@types/react-dom": "^16.9.8",
"@types/react-redux": "^7.1.9",
"@types/react-router": "^5.1.7",
Expand Down
1 change: 1 addition & 0 deletions src/frontend/components/design-system/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ export * from './molecules/drawer'
export * from './molecules/logged-user'
export * from './molecules/nav-group'
export * from './molecules/stepper'
export * from './utils/date-utils'

export * from './templates/navigation'
52 changes: 21 additions & 31 deletions src/frontend/components/design-system/molecules/date-picker.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState } from 'react'
import ReactDatePicker from 'react-datepicker'
import ReactDatePicker, { ReactDatePickerProps } from 'react-datepicker'
import styled from 'styled-components'

import styles from '../utils/datepicker.styles'
Expand All @@ -8,7 +8,8 @@ import { Button } from '../atoms/button'
import { Icon } from '../atoms/icon'
import { InputGroup } from './form-group'
import { cssClass } from '../utils/css-class'

import { PropertyType } from '../../../../backend/adapters/base-property'
import { formatDateProperty } from '../utils/date-utils'

const StyledDatePicker = styled(InputGroup)`
${styles};
Expand Down Expand Up @@ -109,12 +110,16 @@ const DatePickerWrapper = styled.div`
top: ${({ theme }): string => theme.space.xxl};
`

type CustomProps = Partial<Omit<ReactDatePickerProps, 'value' | 'disabled' | 'onChange'>>

/**
* Props for DatePicker
* @memberof DatePicker
* @alias DatePickerProps
* @property {any} {...} Any custom props to pass down to the ReactDatePicker
* @see {https://reactdatepicker.com/}
*/
export type DatePickerProps = {
export type DatePickerProps = CustomProps & {
/**
* If datepicker should be disabled
*/
Expand All @@ -128,31 +133,9 @@ export type DatePickerProps = {
*/
onChange: (date: string) => void;
/**
* Any custom props to pass down to the ReactDatePicker
* property type, date or datetime
*/
propertyType?: string;

/**
* Any custom props to pass down to the ReactDatePicker
* property type, could be either 'date' or 'datetime'
*/
[key: string]: any;
}

const pad = (n: number): string => (n < 10 ? `0${n.toString()}` : n.toString())

const formatDate = (date: Date): string => `${date.getFullYear()}-${pad(date.getMonth() + 1)
}-${pad(date.getDate())}`

const formatTime = (date: Date): string => `${pad(date.getHours())}:${pad(date.getMinutes())}`

const formatDateTime = (date: Date): string => `${formatDate(date)} ${formatTime(date)}`

const formatType = (date: Date, propertyType: string | undefined): string => {
if (propertyType === 'date') {
return formatDate(date)
}
return formatDateTime(date)
propertyType?: PropertyType;
}

/**
Expand All @@ -176,20 +159,21 @@ export const DatePicker: React.FC<DatePickerProps> = (props) => {
const [hidden, setHidden] = useState(true)

let dateValue: Date | undefined
let stringValue: string | undefined = value && value.toString()
let stringValue: string | undefined

if (value && value.constructor.name !== 'Date') {
const dateNum = Date.parse(value as string) || undefined
if (dateNum) {
dateValue = new Date(dateNum)
stringValue = formatDateProperty(dateValue, propertyType)
}
} else if (value && value.constructor.name === 'Date') {
stringValue = formatType(value as Date, propertyType)
stringValue = formatDateProperty(value as Date, propertyType)
}

const onDatePickerChange = (date: Date): void => {
if (!disabled) {
onChange(formatType(date, propertyType))
onChange(formatDateProperty(date, propertyType))
}
}

Expand Down Expand Up @@ -217,7 +201,13 @@ export const DatePicker: React.FC<DatePickerProps> = (props) => {
</Button>
{!hidden ? (
<DatePickerWrapper>
<ReactDatePicker selected={dateValue} onChange={onDatePickerChange} inline {...other} />
<ReactDatePicker
selected={dateValue}
onChange={onDatePickerChange}
inline
showTimeInput={propertyType === 'datetime'}
{...other}
/>
</DatePickerWrapper>
) : ''}
</StyledDatePicker>
Expand Down
56 changes: 56 additions & 0 deletions src/frontend/components/design-system/utils/date-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { PropertyType } from '../../../../backend/adapters/base-property'

/**
* adds leading 0 to the number when it is lower than 10
* @private
*/
const pad = (n: number): string => (n < 10 ? `0${n.toString()}` : n.toString())

/**
* Formats date to YYYY-MM-DD
*
* @param {Date} date
* @return {string}
* @private
*/
const formatDate = (date: Date): string => `${date.getFullYear()}-${pad(date.getMonth() + 1)
}-${pad(date.getDate())}`

/**
* Formats date to HH:mm
*
* @param {Date} date
* @return {string}
* @private
*/
const formatTime = (date: Date): string => `${pad(date.getHours())}:${pad(date.getMinutes())}`

/**
* Formats date to YYYY-MM-DD HH:mm
*
* @param {Date} date
* @return {string}
* @private
*/
const formatDateTime = (date: Date): string => `${formatDate(date)} ${formatTime(date)}`

/**
* Based on the property type formats date to either YYYY-MM-DD HH:mm or YYYY-MM-DD
*
* @param {Date} date
* @return {string}
* @private
*/
const formatDateProperty = (date: Date, propertyType?: PropertyType): string => {
if (propertyType === 'date') {
return formatDate(date)
}
return formatDateTime(date)
}

export {
formatDateProperty,
formatDate,
formatDateTime,
pad,
}
2 changes: 1 addition & 1 deletion src/frontend/components/property-type/datetime/edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const Edit: React.FC<EditPropertyProps> = (props) => {
value={value}
disabled={property.isDisabled}
onChange={(data: string): void => onChange(property.name, data)}
propertyType={property.type}
propertyType={property.type}
{...property.custom}
/>
<FormMessage>{error && error.message}</FormMessage>
Expand Down
2 changes: 2 additions & 0 deletions src/frontend/components/property-type/datetime/filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ const Filter: React.FC<FilterPropertyProps> = (props) => {
<DatePicker
value={fromValue}
onChange={(data: string): void => onChange(fromKey, data)}
propertyType={property.type}
/>
<Label mt="default">- To: </Label>
<DatePicker
value={toValue}
onChange={(data: string): void => onChange(toKey, data)}
propertyType={property.type}
/>
</FormGroup>
</React.Fragment>
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/components/property-type/datetime/list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ interface Props {
export default class List extends React.PureComponent<Props> {
render(): React.ReactChild {
const { property, record } = this.props
const value = mapValue(record.params[property.name])
const value = mapValue(record.params[property.name], property.type)

return (
<span>{value}</span>
Expand Down
10 changes: 8 additions & 2 deletions src/frontend/components/property-type/datetime/map-value.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
export default (value: Date): string => {
import { formatDateProperty } from '../../design-system'
import { PropertyType } from '../../../../backend/adapters/base-property'

export default (value: Date, propertyType: PropertyType): string => {
if (!value) {
return ''
}
const date = new Date(value)
return date.toLocaleString()
if (date) {
return formatDateProperty(date, propertyType)
}
return ''
}
2 changes: 1 addition & 1 deletion src/frontend/components/property-type/datetime/show.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { EditPropertyProps } from '../base-property-props'
export default class Show extends React.PureComponent<EditPropertyProps> {
render(): ReactNode {
const { property, record } = this.props
const value = mapValue(record.params[property.name])
const value = mapValue(record.params[property.name], property.type)

return (
<FormGroup>
Expand Down
11 changes: 10 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1787,6 +1787,15 @@
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==

"@types/react-datepicker@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@types/react-datepicker/-/react-datepicker-3.1.0.tgz#e55d23224479346cc0405fbe1215017413243419"
integrity sha512-NhI001C2W5Sx6aOxKC1P1bvl8WB3PwxGOJ0bTimf7GcjPY2qIfhtFaSnCHZ+rLUQjG7O75UDXpMc0fEEej11dw==
dependencies:
"@types/react" "*"
date-fns "^2.0.1"
popper.js "^1.14.1"

"@types/react-dom@^16.9.8":
version "16.9.8"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.8.tgz#fe4c1e11dfc67155733dfa6aa65108b4971cb423"
Expand Down Expand Up @@ -8501,7 +8510,7 @@ polished@^3.4.2:
dependencies:
"@babel/runtime" "^7.6.3"

popper.js@^1.14.4:
popper.js@^1.14.1, popper.js@^1.14.4:
version "1.16.1"
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b"
integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==
Expand Down

0 comments on commit 961d67d

Please sign in to comment.