ember-frost-bunsen
Version:
Create UI's from JSON configurations.
241 lines (204 loc) • 7.44 kB
JavaScript
import Ember from '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'
export default AbstractInput.extend({
// == Component Properties ===================================================
classNameBindings: ['value:frost-bunsen-has-value'],
classNames: [
'frost-bunsen-input-when',
'frost-field'
],
layout,
DEFAULT_TIMEZONE,
propTypes: {
// private
date: PropTypes.string,
dateValue: PropTypes.string,
firstButtonValue: PropTypes.string,
selectedValue: PropTypes.string,
storedDateTimeValue: PropTypes.string,
time: PropTypes.string
},
getDefaultProps () {
return {
dateValue: DATE_VALUE
}
},
// == Computed Properties ====================================================
/**
* A unique ID to be used in order to find the date-picker to enable/disable
* @returns {String} unique ID for the date-time-picker
*/
dateId () {
return guidFor(this) + '_dateId'
},
/**
* The date format to be used in the date-time-picker
* @param {Object} cellConfig - contains the dateFormat "string" property (a valid moment format)
* @see {@link https://momentjs.com/docs/#/displaying/format}
* @returns {String} the date format
*/
dateFormat (cellConfig) {
return get(cellConfig, 'renderer.dateFormat') || 'YYYY-MM-DD'
},
/**
* The time format to be used in the date-time-picker
* @param {Object} cellConfig - contains the timeFormat "string" property (a valid moment format)
* @see {@link https://momentjs.com/docs/#/displaying/format}
* @returns {String} the time format
*/
timeFormat (cellConfig) {
return get(cellConfig, 'renderer.timeFormat') || 'HH:mm:ss'
},
/**
* The date time format to be used for formating the value sent to the bunsen model
* @param {Object} cellConfig - contains the dateTimeFormat "string" property (a valid moment format)
* @see {@link https://momentjs.com/docs/#/displaying/format}
* @returns {String} the date time format
*/
dateTimeFormat (cellConfig) {
return get(cellConfig, 'renderer.dateTimeFormat') || 'YYYY-MM-DDTHH:mm:ssZ'
},
/**
* The unique "Id" for the radio group
* @returns {String} the unique id
*/
groupId () {
return guidFor(this) + '_radioGroup'
},
/**
* The size to be used for the radio buttons
* @param {Object} cellConfig - contains the size "string" property (a valid frost-radio-button size)
* @returns {String} the radio button size
*/
size (cellConfig) {
return get(cellConfig, 'renderer.size') || 'small'
},
timezone (cellConfig) {
return getWithDefault(cellConfig, 'renderer.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 ==============================================================
/**
* Initializes the component properties, sets the first radio button as selected and
* sets the bunsen model to the value of the first radio button
* @returns {undefined}
*/
init () {
this._super(...arguments)
const firstButtonValue = get(this, 'cellConfig.renderer.value')
const value = this.get('value')
const timezone = this.get('timezone')
let selectedValue = firstButtonValue
let currentDateTime = getMomentTimezone(undefined, timezone)
if (isPresent(value) && value !== firstButtonValue) {
selectedValue = DATE_VALUE
currentDateTime = getMomentTimezone(value, timezone)
}
const date = currentDateTime.format(this.get('dateFormat'))
const time = currentDateTime.format(this.get('timeFormat'))
this.setProperties({
date,
firstButtonValue,
selectedValue,
storedDateTimeValue: getFormattedTime(currentDateTime, this.get('dateTimeFormat'), timezone),
time,
localTimezone: moment().format('Z')
})
if (!isPresent(value)) {
run.schedule('afterRender', () => {
this.onChange(this.get('bunsenId'), firstButtonValue)
})
}
},
/**
* Disables the date-time-picker "<inputs>" upon startup
* @returns {undefined}
*/
didInsertElement () {
this._super(...arguments)
this._setDisabled(this.get('selectedValue') === this.get('firstButtonValue'))
},
/**
* Enables/disables the date-time-picker "<inputs>"
* @param {Boolean} state - whether to enable or disable the date-time-picker
* @returns {undefined}
*/
_setDisabled (state) {
const id = this.get('dateId')
this.$(`#${id} input`).each(function () {
$(this).prop('disabled', state)
})
},
// == Actions ===============================================================
actions: {
/**
* Manages which radio button is selected and sets the bunsen model to the value
* of the selected button or value of the date-picker selection
* @param {Object} event - the event object of the selection
* @returns {undefined}
*/
selectedButton (event) {
const value = event.target.value
const firstButtonValue = this.get('firstButtonValue')
// Set the bunsen model to the value of the selected button
let newValue
if (value === firstButtonValue) {
newValue = firstButtonValue
} else if (value === DATE_VALUE) {
newValue = this.get('storedDateTimeValue')
} else {
return
}
// If the value of the button did not change for an existing value we don't want to track it
const radioValues = [firstButtonValue, DATE_VALUE]
if (radioValues.includes(value)) {
this.set('selectedValue', value)
// Disable the date-time-picker when it's radio button is not selected
this._setDisabled(newValue === firstButtonValue)
}
// protecting against initial render onChange
run.schedule('afterRender', () => {
this.onChange(this.get('bunsenId'), newValue)
})
},
/**
* 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.set('storedDateTimeValue', formattedTime)
this.onChange(this.get('bunsenId'), formattedTime)
}
}
})