diff --git a/internal_packages/composer-signature/lib/preferences-signatures.cjsx b/internal_packages/composer-signature/lib/preferences-signatures.cjsx index 76b81a140..14b477f9d 100644 --- a/internal_packages/composer-signature/lib/preferences-signatures.cjsx +++ b/internal_packages/composer-signature/lib/preferences-signatures.cjsx @@ -59,7 +59,7 @@ class PreferencesSignatures extends React.Component _renderAccountPicker: -> options = @state.accounts.map (account) -> - {account.emailAddress} + {account.emailAddress} {options} diff --git a/internal_packages/events/lib/event-component.cjsx b/internal_packages/events/lib/event-component.cjsx deleted file mode 100644 index 632abf134..000000000 --- a/internal_packages/events/lib/event-component.cjsx +++ /dev/null @@ -1,107 +0,0 @@ -_ = require 'underscore' -path = require 'path' -React = require 'react' -{RetinaImg} = require 'nylas-component-kit' -{Actions, -Event, -Utils, -ComponentRegistry, -AccountStore} = require 'nylas-exports' -EventRSVPTask = require './tasks/event-rsvp' -moment = require 'moment-timezone' - -class EventComponent extends React.Component - @displayName: 'EventComponent' - - @propTypes: - event: React.PropTypes.object.isRequired - - constructor: (@props) -> - # Since getting state is asynchronous, default to empty values - @state = @_nullEvent() - - _nullEvent: -> - participants: [] - title: "" - when: {start_time: 0} - - _onChange: => - DatabaseStore.find(Event, @props.event.id).then (event) => - event ?= @_nullEvent() - @setState(event) - - componentDidMount: -> @_onChange() - - componentWillMount: -> - @usubs.push DatabaseStore.listen (change) => - @_onChange() if change.objectClass is Event.name - @usubs.push AccountStore.listen(@_onChange) - - componentWillUnmount: -> usub?() for usub in @usubs() - - _myStatus: => - myEmail = AccountStore.current()?.me().email - for p in @state.participants - if p['email'] == myEmail - return p['status'] - - return null - - render: => - - - - Event: {@state.title} - - - - - {moment(@state.when['start_time']*1000).tz(Utils.timeZone).format("dddd, MMMM Do")} - - - - {moment(@state.when['start_time']*1000).tz(Utils.timeZone).format("h:mm a z")} - - {@_renderEventActions()} - - - - - - _renderEventActions: => - - {@_renderAcceptButton()} - {@_renderMaybeButton()} - {@_renderDeclineButton()} - - - _renderAcceptButton: -> - classes = "btn-rsvp" - if @_myStatus() == "yes" - classes += " yes" - @_rsvp("yes")}> - Accept - - - _renderDeclineButton: -> - classes = "btn-rsvp" - if @_myStatus() == "no" - classes += " no" - @_rsvp("no")}> - Decline - - - _renderMaybeButton: -> - classes = "btn-rsvp" - if @_myStatus() == "maybe" - classes += " maybe" - @_rsvp("maybe")}> - Maybe - - - _rsvp: (status) -> - Acitions.queueTask(new EventRSVPTask(@state, status)) - - -module.exports = EventComponent diff --git a/internal_packages/events/lib/event-header.cjsx b/internal_packages/events/lib/event-header.cjsx new file mode 100644 index 000000000..3186a257a --- /dev/null +++ b/internal_packages/events/lib/event-header.cjsx @@ -0,0 +1,93 @@ +_ = require 'underscore' +path = require 'path' +React = require 'react' +{RetinaImg} = require 'nylas-component-kit' +{Actions, + Message, + Event, + Utils, + ComponentRegistry, + EventRSVPTask, + DatabaseStore, + AccountStore} = require 'nylas-exports' +moment = require 'moment-timezone' + +class EventHeader extends React.Component + @displayName: 'EventHeader' + + @propTypes: + message: React.PropTypes.instanceOf(Message).isRequired + + constructor: (@props) -> + @state = + event: @props.message.events[0] + + _onChange: => + return unless @state.event + DatabaseStore.find(Event, @state.event.id).then (event) => + return unless event + @setState({event}) + + componentDidMount: => + @_unlisten = DatabaseStore.listen (change) => + if change.objectClass is Event.name + updated = _.find change.objects, (o) => o.id is @state.event.id + @setState({event: updated}) if updated + @_onChange() + + componentWillReceiveProps: (nextProps) => + @setState({event:nextProps.message.events[0]}) + @_onChange() + + componentWillUnmount: => + @_unlisten?() + + _myStatus: => + myEmail = AccountStore.current()?.me().email + for p in @state.event.participants + return p['status'] if p['email'] is myEmail + return null + + render: => + if @state.event? + + + + Event: {@state.event.title} + + + + + {moment(@state.event.when['start_time']*1000).tz(Utils.timeZone).format("dddd, MMMM Do")} + + + + {moment(@state.event.when['start_time']*1000).tz(Utils.timeZone).format("h:mm a z")} + + {@_renderEventActions()} + + + + + else + + + _renderEventActions: => + actions = [["yes", "Accept"], ["maybe", "Maybe"], ["no", "Decline"]] + + + {actions.map ([status, label]) => + classes = "btn-rsvp " + classes += status if @_myStatus() is status + @_rsvp(status)}> + {label} + + } + + + _rsvp: (status) => + Actions.queueTask(new EventRSVPTask(@state.event, status)) + + +module.exports = EventHeader diff --git a/internal_packages/events/lib/main.cjsx b/internal_packages/events/lib/main.cjsx index 59bbb296b..830db1928 100644 --- a/internal_packages/events/lib/main.cjsx +++ b/internal_packages/events/lib/main.cjsx @@ -1,12 +1,12 @@ -# {ComponentRegistry, WorkspaceStore} = require 'nylas-exports' -# EventComponent = require "./event-component" +{ComponentRegistry, WorkspaceStore} = require 'nylas-exports' +EventHeader = require "./event-header" module.exports = activate: (@state={}) -> - # ComponentRegistry.register EventComponent, - # role: 'Event' + ComponentRegistry.register EventHeader, + role: 'message:BodyHeader' deactivate: -> - # ComponentRegistry.unregister(EventComponent) + ComponentRegistry.unregister(EventHeader) serialize: -> @state diff --git a/internal_packages/events/stylesheets/events.less b/internal_packages/events/stylesheets/events.less index 4f898b8a4..a73da41c3 100644 --- a/internal_packages/events/stylesheets/events.less +++ b/internal_packages/events/stylesheets/events.less @@ -6,16 +6,16 @@ position: relative; font-size: @font-size-small; margin-top: @spacing-standard; - box-shadow: inset 0 0 1px 1px rgba(0,0,0,0.09); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; width: 100%; display: inline-block; border-radius: @border-radius-base; + border: 1px solid @border-color-divider; .event-header{ - border-bottom: 1px solid lighten(@border-color-divider, 6%); + border-bottom: 1px solid @border-color-divider; padding: 10px; img{ diff --git a/internal_packages/message-autoload-images/lib/autoload-images-header.cjsx b/internal_packages/message-autoload-images/lib/autoload-images-header.cjsx index 88bf7d465..0b6582453 100644 --- a/internal_packages/message-autoload-images/lib/autoload-images-header.cjsx +++ b/internal_packages/message-autoload-images/lib/autoload-images-header.cjsx @@ -1,10 +1,14 @@ React = require 'react' AutoloadImagesStore = require './autoload-images-store' Actions = require './autoload-images-actions' +{Message} = require 'nylas-exports' class AutoloadImagesHeader extends React.Component @displayName: 'AutoloadImagesHeader' + @propTypes: + message: React.PropTypes.instanceOf(Message).isRequired + constructor: (@props) -> render: => diff --git a/internal_packages/message-list/lib/message-item.cjsx b/internal_packages/message-list/lib/message-item.cjsx index 70e7e369c..fd4f0c609 100644 --- a/internal_packages/message-list/lib/message-item.cjsx +++ b/internal_packages/message-list/lib/message-item.cjsx @@ -80,7 +80,6 @@ class MessageItem extends React.Component {@_renderHeader()} - {@_renderEvents()} {@_renderAttachments()} @@ -156,13 +155,6 @@ class MessageItem extends React.Component else - _renderEvents: => - events = @_eventComponents() - if events.length > 0 and not Utils.looksLikeGmailInvite(@props.message) - {events} - else - - _renderHeaderSideItems: -> styles = position: "absolute" @@ -227,16 +219,6 @@ class MessageItem extends React.Component return otherAttachments.concat(imageAttachments) - _eventComponents: => - events = @props.message.events.map (e) => - - - return events - _isRealFile: (file) -> hasCIDInBody = file.contentId? and @props.message.body?.indexOf(file.contentId) > 0 return not hasCIDInBody diff --git a/internal_packages/preferences/lib/preferences-sidebar.cjsx b/internal_packages/preferences/lib/preferences-sidebar.cjsx index 57c825c14..5a0232feb 100644 --- a/internal_packages/preferences/lib/preferences-sidebar.cjsx +++ b/internal_packages/preferences/lib/preferences-sidebar.cjsx @@ -46,7 +46,9 @@ class PreferencesSidebarItem extends React.Component "subitem": true "active": account.id is @props.selection.get('accountId') - @_onClickAccount(event, account.id)}> + @_onClickAccount(event, account.id)}> {account.emailAddress} else diff --git a/internal_packages/preferences/lib/tabs/config-schema-item.cjsx b/internal_packages/preferences/lib/tabs/config-schema-item.cjsx index e069d54fd..f5268ea92 100644 --- a/internal_packages/preferences/lib/tabs/config-schema-item.cjsx +++ b/internal_packages/preferences/lib/tabs/config-schema-item.cjsx @@ -23,6 +23,7 @@ class ConfigSchemaItem extends React.Component {_str.humanize(@props.keyName)} {_.pairs(@props.configSchema.properties).map ([key, value]) => {@props.configSchema.title}: {_.zip(@props.configSchema.enum, @props.configSchema.enumLabels).map ([value, label]) => - {label} + {label} } diff --git a/spec/utils-spec.coffee b/spec/utils-spec.coffee index 300ae6918..2298cf535 100644 --- a/spec/utils-spec.coffee +++ b/spec/utils-spec.coffee @@ -22,7 +22,7 @@ describe "modelFreeze", -> b: 2 Utils.modelFreeze(o) expect(Object.isFrozen(o)).toBe(true) - + it "should not throw an exception when nulls appear in strange places", -> t = new Thread(participants: [new Contact(email: 'ben@nylas.com'), null], subject: '123') Utils.modelFreeze(t) @@ -348,141 +348,6 @@ describe "isEqual", -> other = {a: 1} ok(!Utils.isEqual(new Foo, other)) -describe "looksLikeGmailInvite", -> - it "should return false for an exchange invite", -> - message = { - body: """ - - - - - - - - - - - - - - - more - details » - - - (No Subject) - - - - - When - - - Thu Jul 30, 2015 10pm – 11pm - GMT (no daylight saving) - - - - Calendar - - - ethan@nylas.com - - - - Who - - - - - - - • - - - Ethan Blackburn - - - organizer - - - - - - • - - - ethan@nylas.com - - - - - - - - - - - - - Going? - - - Yes - - - - Maybe - - - - No - more - options » - - - - - Invitation from - Google Calendar - You are receiving this email at the account ethan@nylas.com because you are subscribed for invitations on calendar ethan@nylas.com. - To stop receiving these emails, please log in to https://www.google.com/calendar/ and change your notification settings for this calendar. - Forwarding this invitation could allow any recipient to modify your RSVP response. - Learn More. - - - - - - - """ - } - - expect(Utils.looksLikeGmailInvite(message)).toEqual(true) - - it "should return true for a gmail invite", -> - message = { - body: """ - - - - - - - - Begin forwarded message: - - From: Originator <originator@nylas.com> - Subject: <> Nylas E-mail Call and Webhooks review - Date: Jul 28 2015, at 2:32 pm - To: random@guy.com <random@guy.com>, Someone Else <someone@else.com> - - - - - Call to review Pipeline Deals email tool and webhooks support. - - - """ - } - describe "subjectWithPrefix", -> it "should replace an existing Re:", -> expect(Utils.subjectWithPrefix("Re: Test Case", "Fwd:")).toEqual("Fwd: Test Case") diff --git a/src/flux/models/utils.coffee b/src/flux/models/utils.coffee index c650e355d..a4a983edc 100644 --- a/src/flux/models/utils.coffee +++ b/src/flux/models/utils.coffee @@ -99,13 +99,6 @@ Utils = return ext in extensions and size > 512 and size < 1024*1024*5 - looksLikeGmailInvite: (message={}) -> - idx = message.body.search('itemtype="http://schema.org/Event"') - if idx == -1 - return false - return true - - # Escapes potentially dangerous html characters # This code is lifted from Angular.js # See their specs here: diff --git a/src/global/nylas-exports.coffee b/src/global/nylas-exports.coffee index 01a9fa6e8..be454f01c 100644 --- a/src/global/nylas-exports.coffee +++ b/src/global/nylas-exports.coffee @@ -88,7 +88,7 @@ class NylasExports # Tasks # These need to be required immediately to populate the TaskRegistry so # we know how to deserialized saved or IPC-sent tasks. - @require "EventRSVP", 'flux/tasks/event-rsvp' + @require "EventRSVPTask", 'flux/tasks/event-rsvp' @require "SendDraftTask", 'flux/tasks/send-draft' @require "FileUploadTask", 'flux/tasks/file-upload-task' @require "DestroyDraftTask", 'flux/tasks/destroy-draft'
Going? - - - Yes - - - - Maybe - - - - No - more - options »
Invitation from - Google Calendar
You are receiving this email at the account ethan@nylas.com because you are subscribed for invitations on calendar ethan@nylas.com.
To stop receiving these emails, please log in to https://www.google.com/calendar/ and change your notification settings for this calendar.
Forwarding this invitation could allow any recipient to modify your RSVP response. - Learn More.
- Begin forwarded message: - - From: Originator <originator@nylas.com> - Subject: <> Nylas E-mail Call and Webhooks review - Date: Jul 28 2015, at 2:32 pm - To: random@guy.com <random@guy.com>, Someone Else <someone@else.com> - - - - - Call to review Pipeline Deals email tool and webhooks support. -