Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…unsen into fix-re-rendering
  • Loading branch information
Sophy Pal committed Aug 4, 2018
2 parents 75e1f53 + c73541c commit 5161627
Show file tree
Hide file tree
Showing 13 changed files with 227 additions and 29 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# 22.4.0 (2018-08-02)

* Add timezone options to `datetime` and `when` renderers


# 22.3.1 (2018-08-01)

* Used keys for `each` to prevent re-rendering when the cell or model hasn't changed
Expand Down
43 changes: 39 additions & 4 deletions addon/components/inputs/datetime.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import Ember from 'ember'
import computed, {readOnly} from 'ember-computed-decorators'
import moment from 'moment'

import AbstractInput from './abstract-input'
import layout from 'ember-frost-bunsen/templates/components/frost-bunsen-input-datetime'
import {DEFAULT_TIMEZONE, getFormattedTime, getMomentTimezone} from 'ember-frost-bunsen/timezone-utils'

const {getWithDefault} = Ember
const DATE_FORMAT = 'YYYY-MM-DD'
const TIME_FORMAT = 'HH:mm:ss'
const DATE_TIME_FORMAT = 'YYYY-MM-DDTHH:mm:ssZ'
Expand All @@ -19,9 +22,16 @@ export default AbstractInput.extend({
],

layout,
DEFAULT_TIMEZONE,

// == Computed Properties ====================================================

@readOnly
@computed('cellConfig')
timezone (cellConfig) {
return getWithDefault(cellConfig, 'renderer.options.timezone', '')
},

@readOnly
@computed('cellConfig.renderer.options.defaultToCurrentDateTime')
defaultToCurrentDateTime (defaultToCurrentDateTime = true) {
Expand All @@ -43,12 +53,14 @@ export default AbstractInput.extend({
},

@readOnly
@computed('defaultToCurrentDateTime', 'value')
currentValue (defaultToCurrentDateTime, value) {
if (!defaultToCurrentDateTime || value) {
@computed('defaultToCurrentDateTime', 'timezone', 'value')
currentValue (defaultToCurrentDateTime, timezone, value) {
if (!defaultToCurrentDateTime) {
return value
}
return moment().format(DATE_TIME_FORMAT)

// need to get rid of timezone offset so the time picker component doesn't alter the time
return getMomentTimezone(value, timezone).format('YYYY-MM-DDTHH:mm:ss')
},

// == Functions ==============================================================
Expand All @@ -57,8 +69,31 @@ export default AbstractInput.extend({
return moment(value).format(DATE_TIME_FORMAT)
},

// == Lifecycle Hooks =======================================================

init () {
this._super(...arguments)

this.setProperties({
localTimezone: moment().format('Z')
})
},

// == Actions ===============================================================

actions: {
/**
* Sets the user's selected date and time to the bunsen model and stores it in the
* case that the user selects away from the date-time picker radio button but then returns
* @param {Object} value - the users selected date/time moment() object
* @returns {undefined}
*/
selectDate (value) {
const timezone = this.get('timezone')
const datetime = getMomentTimezone(value, timezone, true)
const formattedTime = getFormattedTime(datetime, this.get('dateTimeFormat'), timezone)

this.onChange(this.get('bunsenId'), formattedTime)
}
}
})
39 changes: 29 additions & 10 deletions addon/components/inputs/when.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import Ember from 'ember'
const {$, get, guidFor, isPresent, run} = Ember
const {$, get, getWithDefault, guidFor, isPresent, run} = Ember
import computed, {readOnly} from 'ember-computed-decorators'
import {PropTypes} from 'ember-prop-types'
import moment from 'moment'

import AbstractInput from './abstract-input'
import layout from 'ember-frost-bunsen/templates/components/frost-bunsen-input-when'
import {DEFAULT_TIMEZONE, getFormattedTime, getMomentTimezone} from 'ember-frost-bunsen/timezone-utils'

export const DATE_VALUE = 'DATE'

Expand All @@ -20,6 +21,7 @@ export default AbstractInput.extend({
],

layout,
DEFAULT_TIMEZONE,

propTypes: {
// private
Expand Down Expand Up @@ -106,6 +108,19 @@ export default AbstractInput.extend({
return get(cellConfig, 'renderer.size') || 'small'
},

@readOnly
@computed('cellConfig')
timezone (cellConfig) {
return getWithDefault(cellConfig, 'renderer.timezone', '')
},

@readOnly
@computed('storedDateTimeValue', 'timezone')
displayStoredDateTimeValue (storedDateTimeValue, timezone) {
// need to get rid of timezone offset so the time picker component doesn't alter the time
return getMomentTimezone(storedDateTimeValue, timezone).format('YYYY-MM-DDTHH:mm:ss')
},

// == Functions ==============================================================

/**
Expand All @@ -118,24 +133,26 @@ export default AbstractInput.extend({

const firstButtonValue = get(this, 'cellConfig.renderer.value')
const value = this.get('value')
const timezone = this.get('timezone')

let selectedValue = firstButtonValue
let currentDateTime = moment()
let currentDateTime = getMomentTimezone(undefined, timezone)

if (isPresent(value) && value !== firstButtonValue) {
selectedValue = DATE_VALUE
currentDateTime = value
currentDateTime = getMomentTimezone(value, timezone)
}

const date = moment(currentDateTime).format(this.get('dateFormat'))
const time = moment(currentDateTime).format(this.get('timeFormat'))
const date = currentDateTime.format(this.get('dateFormat'))
const time = currentDateTime.format(this.get('timeFormat'))

this.setProperties({
date,
firstButtonValue,
selectedValue,
storedDateTimeValue: moment(currentDateTime).format(this.get('dateTimeFormat')),
time
storedDateTimeValue: getFormattedTime(currentDateTime, this.get('dateTimeFormat'), timezone),
time,
localTimezone: moment().format('Z')
})

if (!isPresent(value)) {
Expand Down Expand Up @@ -212,10 +229,12 @@ export default AbstractInput.extend({
* @returns {undefined}
*/
selectDate (value) {
const datetime = moment(value).format(this.get('dateTimeFormat'))
const timezone = this.get('timezone')
const datetime = getMomentTimezone(value, timezone, true)
const formattedTime = getFormattedTime(datetime, this.get('dateTimeFormat'), timezone)

this.set('storedDateTimeValue', datetime)
this.onChange(this.get('bunsenId'), datetime)
this.set('storedDateTimeValue', formattedTime)
this.onChange(this.get('bunsenId'), formattedTime)
}
}
})
10 changes: 9 additions & 1 deletion addon/templates/components/frost-bunsen-input-datetime.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,19 @@
defaultTime=(readonly time)
onFocusIn=(action 'hideErrorMessage')
onFocusOut=(action 'showErrorMessage')
onChange=(action 'handleChange')
onChange=(action 'selectDate')
options=cellConfig.renderer.options
}}
</div>
{{/if}}
{{#if timezone}}
<div class="frost-bunsen-cell timezone-container">
<div class="frost-bunsen-left-label timezone-label">Timezone</div>
<div class='timezone-value'>
{{if (eq timezone DEFAULT_TIMEZONE) localTimezone timezone}}
</div>
</div>
{{/if}}
{{#if renderErrorMessage}}
<div class="frost-bunsen-error">
{{renderErrorMessage}}
Expand Down
34 changes: 22 additions & 12 deletions addon/templates/components/frost-bunsen-input-when.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,29 @@
size=size
value=dateValue
}}
{{frost-date-time-picker
id=dateId
hook=(concat hook '-radio-button')
dateFormat=dateFormat
timeFormat=timeFormat
defaultDate=(readonly date)
defaultTime=(readonly time)
onFocusIn=(action 'hideErrorMessage')
onFocusOut=(action 'showErrorMessage')
onChange=(action 'selectDate')
value=storedDateTimeValue
}}
<div class='date-time-label'>
{{frost-date-time-picker
id=dateId
hook=(concat hook '-radio-button')
dateFormat=dateFormat
timeFormat=timeFormat
defaultDate=(readonly date)
defaultTime=(readonly time)
onFocusIn=(action 'hideErrorMessage')
onFocusOut=(action 'showErrorMessage')
onChange=(action 'selectDate')
value=displayStoredDateTimeValue
}}
</div>
{{/controls.button}}
{{#if timezone}}
<div class="frost-bunsen-cell timezone-container">
<div class="frost-bunsen-left-label timezone-label">Timezone</div>
<div class='timezone-value'>
{{if (eq timezone DEFAULT_TIMEZONE) localTimezone timezone}}
</div>
</div>
{{/if}}
{{/frost-radio-group}}
{{#if renderErrorMessage}}
<div class="frost-bunsen-error">
Expand Down
18 changes: 18 additions & 0 deletions addon/timezone-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Ember from 'ember'
import moment from 'moment'
const {isBlank} = Ember

export const DEFAULT_TIMEZONE = 'local'
const DATE_TIME_TIMEZONE_FORMAT = 'YYYY-MM-DDTHH:mm:ssZ'

export function getMomentTimezone (time, timezone, keepLocalTime) {
if (isBlank(timezone) || timezone === DEFAULT_TIMEZONE) {
return moment(time).local()
}

return moment(time).utcOffset(timezone, keepLocalTime)
}

export function getFormattedTime (time, dateTimeFormat, timezone) {
return isBlank(timezone) ? time.format(dateTimeFormat) : time.format(DATE_TIME_TIMEZONE_FORMAT)
}
9 changes: 9 additions & 0 deletions app/styles/ember-frost-bunsen/base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,15 @@ form > div > .frost-bunsen-section {
}
}

.frost-bunsen-input-when,
.frost-bunsen-input-datetime {
.timezone-container {
display: flex;
justify-content: flex-end;
font-weight: 200;
}
}

.frost-bunsen-input-form {
.error,
.frost-bunsen-error {
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ember-frost-bunsen",
"version": "22.3.1",
"version": "22.4.0",
"description": "Create UI's from JSON configurations.",
"frostGuideDirectory": "design-patterns/forms/overview",
"directories": {
Expand Down
20 changes: 20 additions & 0 deletions tests/dummy/app/pods/view/renderers/documentation/datetime.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,24 @@ By default, is no value is given to the renderer, it will display the current da
}
}
}
```

##### timezone

The `timezone` option can be used to add a timezone to the date.
By default, if no value is given to the renderer, it will use a local timezone. If the
`timezone` option is given, the timezone will be shown in the renderer and the value will use
that timezone.

```json
{
"label": "Bar",
"model": "foo",
"renderer": {
"name": "datetime",
"options": {
"timezone": "+08:00"
}
}
}
```
17 changes: 17 additions & 0 deletions tests/dummy/app/pods/view/renderers/documentation/when.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,20 @@ The value for the first radio button
}
}
```

#### renderer.timezone

The `timezone` option can be used to add a timezone to the date.
By default, if no value is given to the renderer, it will use a local timezone. If the
`timezone` option is given, the timezone will be shown in the renderer and the value will use
that timezone.

```json
{
"model": "foo",
"renderer": {
"name": "when",
"timezone": "+08:00"
}
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -456,4 +456,33 @@ describe('Integration: Component / frost-bunsen-form / renderer / datetime', fun
expect($hook('bunsenForm-foo-datetimePicker-time-picker-input')).to.have.value('')
})
})

describe('when timezone property is set', function () {
beforeEach(function () {
this.set('bunsenView', {
cells: [
{
model: 'foo',
renderer: {
name: 'datetime',
options: {
timezone: '+08:00'
}
}
}
],
type: 'form',
version: '2.0'
})

return wait()
})

it('renders as expected', function () {
const timezoneValue = $hook('bunsenForm-foo').find('.timezone-value')

expect(timezoneValue).to.have.length(1)
expect(timezoneValue.text().trim()).to.eql('+08:00')
})
})
})
Loading

0 comments on commit 5161627

Please sign in to comment.