Mailspring/internal_packages/composer/lib/expanded-participants.cjsx
Juan Tejada 281e458d39 feat(account-prefs): Adds new page for Account in preferences
Summary:
Adds the new Account preferences page. This consists of two major React components,
PreferencesAccountList and PreferencesAccountDetails, both of which use EditableList.

I added a bunch of fixes and updated the API for EditableList, plus a bit of
refactoring for PreferencesAccount component, and a bunch of CSS so its a big diff.

The detailed changelog:

Updates to EditableList:
  - Fix bug updating selection state when arrows pressed to move selection
  - Add new props:
    - allowEmptySelection to allow the list to have no selection
    - createInputProps to pass aditional props to the createInput
  - Add scroll region for list items
  - Update styles and refactor render methods

Other Updates:
- Updates Account model to hold aliases and a label
  - Adds getter for label to default to email
- Update accountswitcher to display label, update styles and spec

- Refactor PreferencesAccounts component:
  - Splits it into smaller components,
  - Removes unused code
- Splits preferences styelsheets into smaller separate stylesheet for
  account page. Adds some updates and fixes (scroll-region padding)
- Update AccountStore to be able to perform updates on an account.
- Adds new Action to update account, and an action to remove account to
  be consistent with Action usage
- Adds components for Account list and Aliases list using EditableList

Test Plan: - All specs pass, but need to write new tests!

Reviewers: bengotow, evan

Reviewed By: bengotow

Differential Revision: https://phab.nylas.com/D2332
2015-12-10 15:27:29 -08:00

156 lines
5 KiB
CoffeeScript

_ = require 'underscore'
React = require 'react'
AccountContactField = require './account-contact-field'
ParticipantsTextField = require './participants-text-field'
{Actions} = require 'nylas-exports'
{RetinaImg} = require 'nylas-component-kit'
Fields = require './fields'
class ExpandedParticipants extends React.Component
@displayName: "ExpandedParticipants"
@propTypes:
# Arrays of Contact objects.
to: React.PropTypes.array
cc: React.PropTypes.array
bcc: React.PropTypes.array
from: React.PropTypes.array
# The account to which the current draft belongs
account: React.PropTypes.object
# Either "fullwindow" or "inline"
mode: React.PropTypes.string
# The field that should be focused
focusedField: React.PropTypes.string
# An enum array of visible fields. Can be any constant in the `Fields`
# dict. We are passed these as props instead of holding it as state
# since this component is frequently unmounted and re-mounted every
# time it is displayed
enabledFields: React.PropTypes.array
# Callback for when a user changes which fields should be visible
onAdjustEnabledFields: React.PropTypes.func
# Callback for the participants change
onChangeParticipants: React.PropTypes.func
# Callback for the field focus changes
onChangeFocusedField: React.PropTypes.func
@defaultProps:
to: []
cc: []
bcc: []
from: []
enabledFields: []
constructor: (@props={}) ->
componentDidMount: =>
@_applyFocusedField()
componentDidUpdate: ->
@_applyFocusedField()
render: ->
<div className="expanded-participants"
ref="participantWrap">
{@_renderFields()}
</div>
_applyFocusedField: ->
if @props.focusedField
return unless @refs[@props.focusedField]
if @refs[@props.focusedField].focus
@refs[@props.focusedField].focus()
else
React.findDOMNode(@refs[@props.focusedField]).focus()
_renderFields: =>
# Note: We need to physically add and remove these elements, not just hide them.
# If they're hidden, shift-tab between fields breaks.
fields = []
fields.push(
<div key="to">
<div className="composer-participant-actions">
{if Fields.Cc not in @props.enabledFields
<span className="header-action show-cc"
onClick={ => @props.onAdjustEnabledFields(show: [Fields.Cc]) }>Cc</span>
}
{ if Fields.Bcc not in @props.enabledFields
<span className="header-action show-bcc"
onClick={ => @props.onAdjustEnabledFields(show: [Fields.Bcc]) }>Bcc</span>
}
{ if Fields.Subject not in @props.enabledFields
<span className="header-action show-subject"
onClick={ => @props.onAdjustEnabledFields(show: [Fields.Subject]) }>Subject</span>
}
{ if @props.mode is "inline"
<span className="header-action show-popout"
title="Popout composer"
style={paddingLeft: "1.5em"}
onClick={@props.onPopoutComposer}>
<RetinaImg name="composer-popout.png"
mode={RetinaImg.Mode.ContentIsMask}
style={{position: "relative", top: "-2px"}}/>
</span>
}
</div>
<ParticipantsTextField
ref={Fields.To}
field='to'
change={@props.onChangeParticipants}
className="composer-participant-field to-field"
onFocus={ => @props.onChangeFocusedField(Fields.To) }
participants={to: @props['to'], cc: @props['cc'], bcc: @props['bcc']} />
</div>
)
if Fields.Cc in @props.enabledFields
fields.push(
<ParticipantsTextField
ref={Fields.Cc}
key="cc"
field='cc'
change={@props.onChangeParticipants}
onEmptied={ => @props.onAdjustEnabledFields(hide: [Fields.Cc]) }
onFocus={ => @props.onChangeFocusedField(Fields.Cc) }
className="composer-participant-field cc-field"
participants={to: @props['to'], cc: @props['cc'], bcc: @props['bcc']} />
)
if Fields.Bcc in @props.enabledFields
fields.push(
<ParticipantsTextField
ref={Fields.Bcc}
key="bcc"
field='bcc'
change={@props.onChangeParticipants}
onEmptied={ => @props.onAdjustEnabledFields(hide: [Fields.Bcc]) }
onFocus={ => @props.onChangeFocusedField(Fields.Bcc) }
className="composer-participant-field bcc-field"
participants={to: @props['to'], cc: @props['cc'], bcc: @props['bcc']} />
)
if Fields.From in @props.enabledFields
fields.push(
<AccountContactField
key="from"
ref={Fields.From}
onChange={ (me) => @props.onChangeParticipants(from: [me]) }
onFocus={ => @props.onChangeFocusedField(Fields.From) }
account={@props.account}
value={@props.from?[0]} />
)
fields
module.exports = ExpandedParticipants