-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Site Settings: add date time format sub-page #11259
Changes from all commits
db973be
d543766
182ded9
28ba0cd
3b20156
ff8e9a6
58b4458
b66ec33
b2aa6ea
0548aa0
227a492
aa8bbb8
6018d26
eebf862
a388e06
3ed84f7
9842128
249647d
8c68099
4c439b2
289e576
6c30526
8eb467d
2c3a1de
a3b40b8
a15c407
a3cf018
7c1edeb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import React from 'react'; | ||
import { localize } from 'i18n-calypso'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import FormFieldset from 'components/forms/form-fieldset'; | ||
import FormInput from 'components/forms/form-text-input'; | ||
import FormLabel from 'components/forms/form-label'; | ||
import FormRadio from 'components/forms/form-radio'; | ||
import FormSettingExplanation from 'components/forms/form-setting-explanation'; | ||
import { phpToMomentDatetimeFormat } from 'lib/formatting'; | ||
import { defaultDateFormats } from './default-formats'; | ||
|
||
export const DateFormatOption = ( { | ||
dateFormat, | ||
disabled, | ||
isCustom, | ||
localizedDate, | ||
setCustomDateFormat, | ||
setDateFormat, | ||
translate, | ||
} ) => ( | ||
<FormFieldset> | ||
<FormLabel> | ||
{ translate( 'Date Format' ) } | ||
</FormLabel> | ||
{ defaultDateFormats.map( format => | ||
<FormLabel key={ format }> | ||
<FormRadio | ||
checked={ ! isCustom && format === dateFormat } | ||
disabled={ disabled } | ||
name="date_format" | ||
onChange={ setDateFormat } | ||
value={ format } | ||
/> | ||
<span>{ localizedDate.format( phpToMomentDatetimeFormat( format ) ) }</span> | ||
</FormLabel> | ||
) } | ||
<FormLabel className="date-time-format__custom-field"> | ||
<FormRadio | ||
checked={ isCustom } | ||
disabled={ disabled } | ||
name="date_format" | ||
onChange={ setCustomDateFormat } | ||
value={ dateFormat } | ||
/> | ||
<span> | ||
{ translate( 'Custom', { comment: 'Custom date/time format field' } ) } | ||
<FormInput | ||
disabled={ disabled } | ||
name="date_format_custom" | ||
onChange={ setCustomDateFormat } | ||
type="text" | ||
value={ dateFormat || '' } | ||
/> | ||
<FormSettingExplanation> | ||
{ isCustom && dateFormat && | ||
translate( 'Preview: %s', { | ||
args: localizedDate.format( phpToMomentDatetimeFormat( dateFormat ) ), | ||
comment: 'Date/time format preview', | ||
} ) | ||
} | ||
</FormSettingExplanation> | ||
</span> | ||
</FormLabel> | ||
</FormFieldset> | ||
); | ||
|
||
export default localize( DateFormatOption ); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import React, { Component } from 'react'; | ||
import { localize } from 'i18n-calypso'; | ||
import { capitalize, includes, pick } from 'lodash'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import Button from 'components/button'; | ||
import Card from 'components/card'; | ||
import SectionHeader from 'components/section-header'; | ||
import DateFormatOption from './date-format-option'; | ||
import StartOfWeekOption from './start-of-week-option'; | ||
import TimeFormatOption from './time-format-option'; | ||
import { defaultDateFormats, defaultTimeFormats } from './default-formats'; | ||
import { getLocalizedDate } from './utils'; | ||
import wrapSettingsForm from '../wrap-settings-form'; | ||
|
||
/** | ||
* Module constant | ||
*/ | ||
const defaultSettings = { | ||
date_format: '', | ||
start_of_week: 0, | ||
time_format: '', | ||
timezone_string: '', | ||
}; | ||
|
||
export class DateTimeFormatOptions extends Component { | ||
state = { | ||
customDateFormat: false, | ||
customTimeFormat: false, | ||
isLoadingSettings: true, | ||
}; | ||
|
||
componentWillReceiveProps( nextProps ) { | ||
const { | ||
fields: { | ||
date_format: dateFormat, | ||
time_format: timeFormat, | ||
}, | ||
} = nextProps; | ||
|
||
if ( ! this.state.isLoadingSettings || '' === dateFormat || '' === timeFormat ) { | ||
return; | ||
} | ||
|
||
this.setState( { | ||
customDateFormat: ! includes( defaultDateFormats, dateFormat ), | ||
customTimeFormat: ! includes( defaultTimeFormats, timeFormat ), | ||
isLoadingSettings: false, | ||
} ); | ||
} | ||
|
||
setFormat = ( name, defaultFormats ) => event => { | ||
const { value: format } = event.currentTarget; | ||
this.props.updateFields( { [ `${ name }_format` ]: format } ); | ||
this.setState( { | ||
[ `custom${ capitalize( name ) }Format` ]: ! includes( defaultFormats, format ), | ||
} ); | ||
}; | ||
|
||
setDateFormat = this.setFormat( 'date', defaultDateFormats ); | ||
|
||
setTimeFormat = this.setFormat( 'time', defaultTimeFormats ); | ||
|
||
setCustomFormat = name => event => { | ||
const { value: format } = event.currentTarget; | ||
this.props.updateFields( { [ `${ name }_format` ]: format } ); | ||
this.setState( { | ||
[ `custom${ capitalize( name ) }Format` ]: true, | ||
} ); | ||
}; | ||
|
||
setCustomDateFormat = this.setCustomFormat( 'date' ); | ||
|
||
setCustomTimeFormat = this.setCustomFormat( 'time' ); | ||
|
||
render() { | ||
const { | ||
fields: { | ||
date_format: dateFormat, | ||
start_of_week: startOfWeek, | ||
time_format: timeFormat, | ||
timezone_string: timezoneString, | ||
}, | ||
handleSelect, | ||
handleSubmitForm, | ||
isRequestingSettings, | ||
isSavingSettings, | ||
translate, | ||
} = this.props; | ||
|
||
const { | ||
customDateFormat, | ||
customTimeFormat, | ||
} = this.state; | ||
|
||
const localizedDate = getLocalizedDate( timezoneString ); | ||
|
||
return ( | ||
<div> | ||
<SectionHeader> | ||
<Button | ||
compact={ true } | ||
onClick={ handleSubmitForm } | ||
primary={ true } | ||
type="submit" | ||
disabled={ isRequestingSettings || isSavingSettings } | ||
> | ||
{ isSavingSettings | ||
? translate( 'Saving…' ) | ||
: translate( 'Save Settings' ) | ||
} | ||
</Button> | ||
</SectionHeader> | ||
<Card> | ||
<form> | ||
<DateFormatOption | ||
dateFormat={ dateFormat } | ||
disabled={ isRequestingSettings } | ||
isCustom={ customDateFormat } | ||
localizedDate={ localizedDate } | ||
setCustomDateFormat={ this.setCustomDateFormat } | ||
setDateFormat={ this.setDateFormat } | ||
/> | ||
<TimeFormatOption | ||
disabled={ isRequestingSettings } | ||
isCustom={ customTimeFormat } | ||
localizedDate={ localizedDate } | ||
setCustomTimeFormat={ this.setCustomTimeFormat } | ||
setTimeFormat={ this.setTimeFormat } | ||
timeFormat={ timeFormat } | ||
/> | ||
<StartOfWeekOption | ||
disabled={ isRequestingSettings } | ||
onChange={ handleSelect } | ||
startOfWeek={ startOfWeek } | ||
/> | ||
</form> | ||
</Card> | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
export default wrapSettingsForm( settings => { | ||
if ( ! settings ) { | ||
return defaultSettings; | ||
} | ||
|
||
const formSettings = pick( settings, [ | ||
'date_format', | ||
'start_of_week', | ||
'time_format', | ||
'timezone_string', | ||
] ); | ||
|
||
// handling `gmt_offset` and `timezone_string` values | ||
const gmt_offset = settings.gmt_offset; | ||
|
||
if ( | ||
! settings.timezone_string && | ||
typeof gmt_offset === 'string' && | ||
gmt_offset.length | ||
) { | ||
formSettings.timezone_string = 'UTC' + | ||
( /\-/.test( gmt_offset ) ? '' : '+' ) + | ||
gmt_offset; | ||
} | ||
|
||
return formSettings; | ||
} )( localize( DateTimeFormatOptions ) ); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
export const defaultDateFormats = [ | ||
'F j, Y', | ||
'Y-m-d', | ||
'm/d/Y', | ||
'd/m/Y', | ||
]; | ||
|
||
export const defaultTimeFormats = [ | ||
'g:i a', | ||
'g:i A', | ||
'H:i', | ||
]; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import React from 'react'; | ||
import { connect } from 'react-redux'; | ||
import { localize } from 'i18n-calypso'; | ||
import page from 'page'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import DateTimeFormatOptions from './date-time-format-options'; | ||
import DocumentHead from 'components/data/document-head'; | ||
import HeaderCake from 'components/header-cake'; | ||
import { getSelectedSite } from 'state/ui/selectors'; | ||
|
||
export const DateTimeFormat = ( { translate, site } ) => { | ||
const goBack = () => { | ||
page( '/settings/general/' + site.slug ); | ||
}; | ||
|
||
return ( | ||
<div className="main main-column date-time-format" role="main"> | ||
<DocumentHead title={ translate( 'Manage Date and Time Format' ) } /> | ||
<HeaderCake onClick={ goBack }> | ||
<h1> | ||
{ translate( 'Date and Time Format' ) } | ||
</h1> | ||
</HeaderCake> | ||
<DateTimeFormatOptions /> | ||
</div> | ||
); | ||
}; | ||
|
||
const mapStateToProps = state => ( { | ||
site: getSelectedSite( state ), | ||
} ); | ||
|
||
export default connect( mapStateToProps )( localize( DateTimeFormat ) ); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import React from 'react'; | ||
import { localize } from 'i18n-calypso'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import FormFieldset from 'components/forms/form-fieldset'; | ||
import FormLabel from 'components/forms/form-label'; | ||
import FormSelect from 'components/forms/form-select'; | ||
|
||
export const StartOfWeekOption = ( { | ||
disabled, | ||
moment, | ||
onChange, | ||
startOfWeek, | ||
translate, | ||
} ) => | ||
<FormFieldset> | ||
<FormLabel> | ||
{ translate( 'Week starts on' ) } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi! I've found a possible matching string that has already been translated 88 times: Help me improve these suggestions: react with 👎 if the suggestion doesn't make any sense, or with 👍 if it's a particularly good one (even if not implemented). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi! I've found a possible matching string that has already been translated 88 times: Help me improve these suggestions: react with 👎 if the suggestion doesn't make any sense, or with 👍 if it's a particularly good one (even if not implemented). |
||
</FormLabel> | ||
<FormSelect | ||
disabled={ disabled } | ||
name="start_of_week" | ||
onChange={ onChange } | ||
value={ startOfWeek || 0 } | ||
> | ||
{ moment.weekdays().map( ( day, index ) => | ||
<option key={ day } value={ index }> | ||
{ day } | ||
</option> | ||
) } | ||
</FormSelect> | ||
</FormFieldset>; | ||
|
||
export default localize( StartOfWeekOption ); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
.date-time-format__custom-field { | ||
.form-radio { | ||
margin-top: 12px; | ||
} | ||
|
||
.form-text-input { | ||
margin: 0 12px; | ||
width: 100px; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ping @aduth and @ockham for internal use of
page()
for routing - nothing significant, just noting another use of itfor new code, should we consider creating a new navigation Redux action whose middleware simply calls
page()
so we can start to phase out the imperative navigation?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be on board with that 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe I'll start targeting this as soon as I close up some HTTP layer work…
a simple middleware could handle many of the
page()
uses methinks