fix(getting-started): New menu item, sample package for devs

This commit is contained in:
Ben Gotow 2015-07-06 14:23:51 -04:00
parent 72dd3171ad
commit f13d0e04a6
11 changed files with 176 additions and 37 deletions

View file

@ -58,9 +58,9 @@ Exports =
WorkspaceStore: require '../src/flux/stores/workspace-store'
FocusedTagStore: require '../src/flux/stores/focused-tag-store'
FocusedContentStore: require '../src/flux/stores/focused-content-store'
FocusedContactsStore: require '../src/flux/stores/focused-contacts-store'
FileUploadStore: require '../src/flux/stores/file-upload-store'
FileDownloadStore: require '../src/flux/stores/file-download-store'
FocusedContactsStore: require '../src/flux/stores/focused-contacts-store'
UnreadCountStore: require '../src/flux/stores/unread-count-store'
# Errors

View file

@ -25,6 +25,9 @@ SettingsPackagesStore = Reflux.createStore
@listenTo SettingsActions.refreshFeaturedPackages, @_refreshFeatured
@listenTo SettingsActions.refreshInstalledPackages, @_refreshInstalled
atom.commands.add 'body',
'application:create-package': => @_onCreatePackage()
@listenTo SettingsActions.createPackage, @_onCreatePackage
@listenTo SettingsActions.updatePackage, @_onUpdatePackage
@listenTo SettingsActions.setGlobalSearchValue, @_onGlobalSearchChange

View file

@ -54,13 +54,14 @@
submenu: [
{ label: 'Toggle Hacker Theme', command: 'application:toggle-theme' }
{ type: 'separator' }
{ label: 'Open In Dev Mode...', command: 'application:open-dev' }
{ label: 'Relaunch with Debug Flags...', command: 'application:open-dev' }
{ type: 'separator' }
{ label: 'Open Detailed Logs', command: 'window:open-errorreporter-logs' }
{ label: 'Ship Detailed Logs to Nylas', command: 'application:ship-logs' }
{ type: 'separator' }
{ label: 'Create a Package...', command: 'application:create-package' }
{ label: 'Run Package Specs...', command: 'application:run-package-specs' }
{ label: 'Run Nylas Mail Specs', command: 'application:run-all-specs' }
{ label: 'Run Package Specs', command: 'application:run-package-specs' }
{ label: 'Toggle Developer Tools', command: 'window:toggle-dev-tools' }
]
}

View file

@ -37,13 +37,14 @@
submenu: [
{ label: 'Toggle Hacker Theme', command: 'application:toggle-theme' }
{ type: 'separator' }
{ label: 'Open In &Dev Mode...', command: 'application:open-dev' }
{ label: 'Relaunch with &Debug Flags...', command: 'application:open-dev' }
{ type: 'separator' }
{ label: 'Open Detailed Logs', command: 'window:open-errorreporter-logs' }
{ label: 'Ship Detailed Logs to Nylas', command: 'application:ship-logs' }
{ type: 'separator' }
{ label: 'Create a Package...', command: 'application:create-package' }
{ label: 'Run Package &Specs...', command: 'application:run-package-specs' }
{ label: 'Run &Nylas Mail Specs', command: 'application:run-all-specs' }
{ label: 'Run Package &Specs', command: 'application:run-package-specs' }
{ label: 'Toggle Developer &Tools', command: 'window:toggle-dev-tools' }
]
}

View file

@ -39,13 +39,14 @@
submenu: [
{ label: 'Toggle Hacker Theme', command: 'application:toggle-theme' }
{ type: 'separator' }
{ label: 'Open In &Dev Mode...', command: 'application:open-dev' }
{ label: 'Relaunch with &Debug Flags...', command: 'application:open-dev' }
{ type: 'separator' }
{ label: 'Open Detailed Logs', command: 'window:open-errorreporter-logs' }
{ label: 'Ship Detailed Logs to Nylas', command: 'application:ship-logs' }
{ type: 'separator' }
{ label: 'Run &Atom Specs', command: 'application:run-all-specs' }
{ label: 'Run Package &Specs', command: 'application:run-package-specs' }
{ label: 'Create a Package...', command: 'application:create-package' }
{ label: 'Run Package &Specs...', command: 'application:run-package-specs' }
{ label: 'Run &Nylas Mail Specs', command: 'application:run-all-specs' }
{ label: 'Toggle Developer &Tools', command: 'window:toggle-dev-tools' }
]
}

View file

@ -1,4 +1,4 @@
## My Package
A sample package for Nylas Mail.
A sample package for Nylas Mail. It demonstrates how to add components to the composer's action bar and the message sidebar. Enjoy!

View file

@ -1,30 +1,19 @@
{Utils, React, ComponentRegistry} = require 'nylas-exports'
{RetinaImg} = require 'nylas-component-kit'
{ComponentRegistry} = require 'nylas-exports'
class MyButton extends React.Component
# Adding a `displayName` makes debugging React easier
@displayName: 'MyButton'
render: =>
<div className="my-package">
<button className="btn btn-toolbar" onClick={@_onClick}>
Hello World
</button>
</div>
#
_onClick: =>
dialog = require('remote').require('dialog')
dialog.showErrorBox('Success!', 'Button was clicked.')
MyComposerButton = require './my-composer-button'
MyMessageSidebar = require './my-message-sidebar'
module.exports =
# Activate is called when the package is loaded. If your package previously
# saved state using `serialize` it is provided.
#
activate: (@state) ->
ComponentRegistry.register MyButton,
ComponentRegistry.register MyComposerButton,
role: 'Composer:ActionButton'
ComponentRegistry.register MyMessageSidebar,
role: 'sidebar:focusedContactInfo'
# Serialize is called when your package is about to be unmounted.
# You can return a state object that will be passed back to your package
# when it is re-activated.
@ -37,4 +26,5 @@ module.exports =
# subscribing to events, release them here.
#
deactivate: ->
ComponentRegistry.unregister(MyButton)
ComponentRegistry.unregister(MyComposerButton)
ComponentRegistry.unregister(MyMessageSidebar)

View file

@ -0,0 +1,43 @@
{Utils, DraftStore, React} = require 'nylas-exports'
{RetinaImg} = require 'nylas-component-kit'
class MyComposerButton extends React.Component
# Note: You should assign a new displayName to avoid naming
# conflicts when injecting your item
@displayName: 'MyComposerButton'
# When you register as a composer button, you receive a
# reference to the draft, and you can look it up to perform
# actions and retrieve data.
@propTypes:
draftLocalId: React.PropTypes.string.isRequired
render: =>
<div className="my-package">
<button className="btn btn-toolbar" onClick={ => @_onClick()} ref="button">
Hello World
</button>
</div>
_onClick: =>
# To retrieve information about the draft, we fetch the current editing
# session from the draft store. We can access attributes of the draft
# and add changes to the session which will be appear immediately.
DraftStore.sessionForLocalId(@props.draftLocalId).then (session) =>
newSubject = "#{session.draft().subject} - It Worked!"
dialog = @_getDialog()
dialog.showMessageBox
title: 'Here we go...'
detail: "Adjusting the subject line To `#{newSubject}`"
buttons: ['OK']
type: 'info'
session.changes.add({subject: newSubject})
_getDialog: =>
require('remote').require('dialog')
module.exports = MyComposerButton

View file

@ -0,0 +1,68 @@
{Utils,
React,
FocusedContactsStore} = require 'nylas-exports'
{RetinaImg} = require 'nylas-component-kit'
class MyMessageSidebar extends React.Component
@displayName: 'MyMessageSidebar'
# Providing container styles tells the app how to constrain
# the column your component is being rendered in. The min and
# max size of the column are chosen automatically based on
# these values.
@containerStyles:
order: 1
maxWidth: 300
minWidth: 200
flexShrink: 0
# This sidebar component listens to the FocusedContactStore,
# which gives us access to the Contact object of the currently
# selected person in the conversation. If you wanted to take
# the contact and fetch your own data, you'd want to create
# your own store, so the flow of data would be:
#
# FocusedContactStore => Your Store => Your Component
#
constructor: (@props) ->
@state = @_getStateFromStores()
componentDidMount: =>
@unsubscribe = FocusedContactsStore.listen(@_onChange)
componentWillUnmount: =>
@unsubscribe()
render: =>
if @state.contact
content = @_renderContent()
else
content = @_renderPlaceholder()
<div className="my-message-sidebar">
{content}
</div>
_renderContent: =>
# Want to include images or other static assets in your components?
# Reference them using the nylas:// URL scheme:
#
# <RetinaImg
# url="nylas://<<package.name>>/assets/checkmark_template@2x.png"
# mode={RetinaImg.Mode.ContentIsMask}/>
#
<div className="header">
<h1>Hi there {@state.contact.name}!</h1>
</div>
_renderPlaceholder: =>
<div> No Data Available </div>
_onChange: =>
@setState(@_getStateFromStores())
_getStateFromStores: =>
contact: FocusedContactsStore.focusedContact()
module.exports = MyMessageSidebar

View file

@ -1,12 +1,19 @@
describe "AccountSidebarStore", ->
xit "should update it's selected ID when the focusTag action fires", ->
true
{ComponentRegistry} = require 'nylas-exports'
{activate, deactivate} = require '../lib/main'
xit "should update when the DatabaseStore emits changes to tags", ->
true
MyMessageSidebar = require '../lib/my-message-sidebar'
MyComposerButton = require '../lib/my-composer-button'
xit "should update when the NamespaceStore emits", ->
true
describe "activate", ->
it "should register the composer button and sidebar", ->
spyOn(ComponentRegistry, 'register')
activate()
expect(ComponentRegistry.register).toHaveBeenCalledWith(MyComposerButton, {role: 'Composer:ActionButton'})
expect(ComponentRegistry.register).toHaveBeenCalledWith(MyMessageSidebar, {role: 'sidebar:focusedContactInfo'})
xit "should provide an array of sections to the sidebar view", ->
true
describe "deactivate", ->
it "should unregister the composer button and sidebar", ->
spyOn(ComponentRegistry, 'unregister')
deactivate()
expect(ComponentRegistry.unregister).toHaveBeenCalledWith(MyComposerButton)
expect(ComponentRegistry.unregister).toHaveBeenCalledWith(MyMessageSidebar)

View file

@ -0,0 +1,25 @@
{React} = require 'nylas-exports'
ReactTestUtils = React.addons.TestUtils
MyComposerButton = require '../lib/my-composer-button'
dialogStub =
showMessageBox: jasmine.createSpy('showMessageBox')
describe "MyComposerButton", ->
beforeEach ->
@component = ReactTestUtils.renderIntoDocument(
<MyComposerButton draftLocalId="test" />
)
it "should render into the page", ->
expect(@component).toBeDefined()
it "should have a displayName", ->
expect(MyComposerButton.displayName).toBe('MyComposerButton')
it "should show a dialog box when clicked", ->
spyOn(@component, '_onClick')
buttonNode = React.findDOMNode(@component.refs.button)
ReactTestUtils.Simulate.click(buttonNode)
expect(@component._onClick).toHaveBeenCalled()