Merge branch 'feat-refactor-layout' of github.com:inboxapp/edgehill into feat-refactor-layout
Conflicts: src/flux/models/utils.coffee
|
@ -248,6 +248,8 @@ module.exports = (grunt) ->
|
|||
src: [
|
||||
'static/**/*.less'
|
||||
]
|
||||
options:
|
||||
imports: ['variables/*.less']
|
||||
|
||||
'download-atom-shell':
|
||||
version: packageJson.atomShellVersion
|
||||
|
@ -262,7 +264,7 @@ module.exports = (grunt) ->
|
|||
authors: 'InboxApp Inc.'
|
||||
loadingGif: path.resolve(__dirname, '..', 'resources', 'win', 'loading.gif')
|
||||
iconUrl: 'https://raw.githubusercontent.com/atom/atom/master/resources/win/atom.ico'
|
||||
setupIcon: path.resolve(__dirname, '..', 'resources', 'win', 'atom.ico')
|
||||
setupIcon: path.resolve(__dirname, '..', 'resources', 'win', 'edgehill.ico')
|
||||
|
||||
shell:
|
||||
'kill-atom':
|
||||
|
@ -281,10 +283,10 @@ module.exports = (grunt) ->
|
|||
ciTasks.push('dump-symbols') if process.platform isnt 'win32'
|
||||
ciTasks.push('set-version', 'lint')
|
||||
ciTasks.push('mkdeb') if process.platform is 'linux'
|
||||
ciTasks.push('create-windows-installer') if process.platform is 'win32'
|
||||
ciTasks.push('test') if process.platform is 'darwin'
|
||||
ciTasks.push('codesign')
|
||||
ciTasks.push('mkdmg') if process.platform is 'darwin'
|
||||
ciTasks.push('create-windows-installer') if process.platform is 'win32'
|
||||
ciTasks.push('publish-edgehill-build') if process.platform is 'darwin'
|
||||
# ciTasks.push('publish-build')
|
||||
grunt.registerTask('ci', ciTasks)
|
||||
|
|
|
@ -21,6 +21,11 @@ module.exports = (grunt) ->
|
|||
cp(path.join(shellAppDir, 'Contents', 'MacOS', 'Atom'),
|
||||
path.join(shellAppDir, 'Contents', 'MacOS', 'Edgehill'))
|
||||
rm path.join(shellAppDir, 'Contents', 'MacOS', 'Atom')
|
||||
else if process.platform is 'win32'
|
||||
cp 'atom-shell', shellAppDir, filter: /default_app/
|
||||
# We can rename atom.exe to edgehill.exe, but all of the node libraries with
|
||||
# native code are hard-linked to a file called atom.exe. For now, let's just
|
||||
# leave it as atom.exe. https://github.com/atom/atom-shell/issues/713
|
||||
else
|
||||
cp 'atom-shell', shellAppDir, filter: /default_app/
|
||||
cp path.join(shellAppDir, 'atom'), path.join(shellAppDir, 'edgehill')
|
||||
|
|
|
@ -41,16 +41,19 @@ module.exports = (grunt) ->
|
|||
args = ['--deep', '--force', '--verbose', '--sign', 'Developer ID Application: InboxApp, Inc.', grunt.config.get('atom.shellAppDir')]
|
||||
spawn {cmd, args}, (error) -> callback(error)
|
||||
when 'win32'
|
||||
spawn {cmd: 'taskkill', args: ['/F', '/IM', 'edgehill.exe']}, ->
|
||||
# TODO: Don't do anything now, because we need a certificate pfx file
|
||||
# issued from a certificate authority, and we don't have one.
|
||||
return callback()
|
||||
spawn {cmd: 'taskkill', args: ['/F', '/IM', 'atom.exe']}, ->
|
||||
cmd = process.env.JANKY_SIGNTOOL ? 'signtool'
|
||||
args = [path.join(grunt.config.get('atom.shellAppDir'), 'edgehill.exe')]
|
||||
args = ['sign', path.join(grunt.config.get('atom.shellAppDir'), 'atom.exe')]
|
||||
|
||||
spawn {cmd, args}, (error) ->
|
||||
return callback(error) if error?
|
||||
|
||||
setupExePath = path.resolve(grunt.config.get('atom.buildDir'), 'installer', 'AtomSetup.exe')
|
||||
if fs.isFileSync(setupExePath)
|
||||
args = [setupExePath]
|
||||
args = ['sign', setupExePath]
|
||||
spawn {cmd, args}, (error) -> callback(error)
|
||||
else
|
||||
callback()
|
||||
|
|
|
@ -55,8 +55,8 @@ AccountSidebarStore = Reflux.createStore
|
|||
namespace = NamespaceStore.current()
|
||||
return unless namespace
|
||||
|
||||
@_sections.forEach (section) =>
|
||||
section.tags.forEach (tag) =>
|
||||
@_sections.forEach (section) ->
|
||||
section.tags.forEach (tag) ->
|
||||
# Some tags don't have unread counts
|
||||
return if tag.id in ['archive', 'drafts', 'sent', 'trash']
|
||||
|
||||
|
|
|
@ -2,21 +2,10 @@ React = require "react"
|
|||
CalendarBar = require "./calendar-bar"
|
||||
|
||||
module.exports =
|
||||
item: null # The DOM item the main React component renders into
|
||||
|
||||
activate: (@state) ->
|
||||
unless @item?
|
||||
@item = document.createElement("div")
|
||||
@item.setAttribute("id", "calendar-bar")
|
||||
@item.setAttribute("class", "calendar-bar")
|
||||
|
||||
React.render(<CalendarBar /> , @item)
|
||||
|
||||
atom.workspace.addRow(@item)
|
||||
|
||||
# Package turned off for now
|
||||
|
||||
deactivate: ->
|
||||
React.unmountComponentAtNode(@item)
|
||||
@item.remove()
|
||||
@item = null
|
||||
|
||||
serialize: -> @state
|
||||
|
|
|
@ -42,7 +42,6 @@ ComposerView = React.createClass
|
|||
@_checkForKnownFrames()
|
||||
|
||||
componentDidMount: ->
|
||||
@undoManager = new UndoManager
|
||||
@keymap_unsubscriber = atom.commands.add '.composer-outer-wrap', {
|
||||
'composer:show-and-focus-bcc': @_showAndFocusBcc
|
||||
'composer:show-and-focus-cc': @_showAndFocusCc
|
||||
|
@ -82,6 +81,8 @@ ComposerView = React.createClass
|
|||
@_prepareForDraft()
|
||||
|
||||
_prepareForDraft: ->
|
||||
# UndoManager must be ready before we call _onDraftChanged for the first time
|
||||
@undoManager = new UndoManager
|
||||
@_proxy = DraftStore.sessionForLocalId(@props.localId)
|
||||
if @_proxy.draft()
|
||||
@_onDraftChanged()
|
||||
|
|
|
@ -35,8 +35,8 @@ ActivityBar = React.createClass
|
|||
render: ->
|
||||
<ResizableRegion className="activity-bar"
|
||||
initialHeight={@state.height}
|
||||
handle={ResizableRegion.Handle.Top}
|
||||
onResize={@_onTrayResized}>
|
||||
minHeight={ActivityBarClosedHeight}
|
||||
handle={ResizableRegion.Handle.Top}>
|
||||
<div className="controls">
|
||||
{@_caret()}
|
||||
<div className="queue-status">
|
||||
|
@ -140,10 +140,6 @@ ActivityBar = React.createClass
|
|||
@setState(section: section)
|
||||
@_onShow()
|
||||
|
||||
_onTrayResized: (height) ->
|
||||
height = ActivityBarClosedHeight if height < 80
|
||||
@setState(height: height)
|
||||
|
||||
_onFeedback: ->
|
||||
user = NamespaceStore.current().name
|
||||
|
||||
|
|
|
@ -7,11 +7,10 @@ module.exports =
|
|||
|
||||
activate: (@state={}) ->
|
||||
# Register our menu item in the composer footer
|
||||
ComponentRegistry.register
|
||||
name: 'TemplatePicker'
|
||||
role: 'Composer:Footer'
|
||||
view: TemplatePicker
|
||||
|
||||
# ComponentRegistry.register
|
||||
# name: 'TemplatePicker'
|
||||
# role: 'Composer:Footer'
|
||||
# view: TemplatePicker
|
||||
|
||||
deactivate: ->
|
||||
|
||||
|
|
|
@ -1,32 +1,24 @@
|
|||
React = require "react"
|
||||
Notifications = require "./notifications"
|
||||
NotificationsStickyBar = require "./notifications-sticky-bar"
|
||||
{ComponentRegistry} = require("inbox-exports")
|
||||
|
||||
module.exports =
|
||||
item: null # The DOM item the main React component renders into
|
||||
|
||||
activate: (@state={}) ->
|
||||
unless @item?
|
||||
@item = document.createElement("div")
|
||||
@item.setAttribute("id", "notifications-wrap")
|
||||
@item.setAttribute("class", "notifications-wrap")
|
||||
atom.workspace.addColumnItem(@item, "thread-list-column")
|
||||
React.render(<Notifications /> , @item)
|
||||
ComponentRegistry.register
|
||||
view: Notifications
|
||||
name: 'Notifications'
|
||||
role: 'ThreadList:Center'
|
||||
|
||||
unless @stickyItem?
|
||||
@stickyItem = document.createElement("div")
|
||||
@stickyItem.setAttribute("id", "notifications-sticky-bar")
|
||||
@stickyItem.setAttribute("class", "notifications-sticky-bar")
|
||||
atom.workspace.addRow(@stickyItem)
|
||||
React.render(<NotificationsStickyBar /> , @stickyItem)
|
||||
ComponentRegistry.register
|
||||
view: NotificationsStickyBar
|
||||
name: 'NotificationsStickyBar'
|
||||
role: 'ThreadList:Top'
|
||||
|
||||
deactivate: ->
|
||||
React.unmountComponentAtNode(@item)
|
||||
@item.remove()
|
||||
@item = null
|
||||
|
||||
React.unmountComponentAtNode(@stickyItem)
|
||||
@stickyItem.remove()
|
||||
@stickyItem = null
|
||||
ComponentRegistry.unregister('NotificationsStickyBar')
|
||||
ComponentRegistry.unregister('Notifications')
|
||||
|
||||
serialize: -> @state
|
||||
|
|
|
@ -41,7 +41,7 @@ NotificationStickyBar = React.createClass
|
|||
@
|
||||
|
||||
render: ->
|
||||
<div>
|
||||
<div className="notifications-sticky">
|
||||
{@_notificationComponents()}
|
||||
</div>
|
||||
|
||||
|
|
|
@ -14,12 +14,17 @@ Notifications = React.createClass
|
|||
@unsubscribeStore() if @unsubscribeStore
|
||||
|
||||
render: ->
|
||||
<div className="notifications">{
|
||||
for notification in @state.notifications
|
||||
<div className={"notification-item notification-#{notification.type}"}>
|
||||
{notification.message}
|
||||
</div>
|
||||
}</div>
|
||||
<div className="notifications-momentary">
|
||||
<div className="inner">
|
||||
{@_notificationComponents()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
_notificationComponents: ->
|
||||
@state.notifications.map (notification) ->
|
||||
<div className={"notification-item notification-#{notification.type}"}>
|
||||
{notification.message}
|
||||
</div>
|
||||
|
||||
_onStoreChange: ->
|
||||
@setState
|
||||
|
|
|
@ -2,35 +2,13 @@
|
|||
@import "ui-mixins";
|
||||
|
||||
// Notification Colors
|
||||
.notifications-wrap, .notifications-sticky-bar {
|
||||
.notifications-momentary,
|
||||
.notifications-sticky {
|
||||
.notification-info { background: @background-color-info; }
|
||||
.notification-error { background: @background-color-error; }
|
||||
.notification-success { background: @background-color-success; }
|
||||
}
|
||||
|
||||
// Notifications Above Threads
|
||||
.notifications-wrap {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
order: 1;
|
||||
z-index: 400;
|
||||
|
||||
.notifications {
|
||||
text-align: center;
|
||||
font-size: @font-size-small;
|
||||
height: 19px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.notification-item {
|
||||
color: @text-color-inverse;
|
||||
padding: 0px 15px 2px 1px;
|
||||
}
|
||||
}
|
||||
|
||||
// Notifications Across Top Bar
|
||||
.notifications-sticky-bar {
|
||||
order: -1;
|
||||
order: -1;
|
||||
|
||||
.notifications-sticky-item {
|
||||
height: 25px;
|
||||
|
@ -65,3 +43,22 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Notifications Above Threads
|
||||
.notifications-momentary {
|
||||
position: absolute;
|
||||
order: 1;
|
||||
z-index: 400;
|
||||
width:100%;
|
||||
|
||||
.inner {
|
||||
text-align: center;
|
||||
font-size: @font-size-small;
|
||||
overflow: auto;
|
||||
|
||||
.notification-item {
|
||||
color: @text-color-inverse;
|
||||
padding: 3px 15px 2px 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ OnboardingActions = require './onboarding-actions'
|
|||
OnboardingStore = require './onboarding-store'
|
||||
querystring = require 'querystring'
|
||||
{EdgehillAPI} = require 'inbox-exports'
|
||||
{RetinaImg} = require 'ui-components'
|
||||
|
||||
module.exports =
|
||||
ContainerView = React.createClass
|
||||
|
@ -30,21 +31,22 @@ ContainerView = React.createClass
|
|||
webview = this.refs['connect-iframe']
|
||||
if webview
|
||||
node = webview.getDOMNode()
|
||||
node.addEventListener 'did-finish-load', (e) ->
|
||||
if node.getUrl().indexOf('/connect/complete') != -1
|
||||
query = node.getUrl().split('?')[1]
|
||||
token = querystring.decode(query)
|
||||
OnboardingActions.finishedConnect(token)
|
||||
if node.hasListeners is undefined
|
||||
node.addEventListener 'did-start-loading', (e) ->
|
||||
if node.hasMobileUserAgent is undefined
|
||||
node.setUserAgent("Mozilla/5.0 (iPhone; CPU iPhone OS 7_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D167 Safari/9537.53")
|
||||
node.hasMobileUserAgent = true
|
||||
node.reload()
|
||||
node.addEventListener 'did-finish-load', (e) ->
|
||||
if node.getUrl().indexOf('/connect/complete') != -1
|
||||
query = node.getUrl().split('?')[1]
|
||||
token = querystring.decode(query)
|
||||
OnboardingActions.finishedConnect(token)
|
||||
|
||||
render: ->
|
||||
<div className={@state.page}>
|
||||
<ReactCSSTransitionGroup transitionName="page">
|
||||
{@_pageComponent()}
|
||||
</ReactCSSTransitionGroup>
|
||||
<div className="quit" onClick={@_fireQuit}><i className="fa fa-times"></i></div>
|
||||
<button className="btn btn-default dismiss" onClick={@_fireDismiss}>Cancel</button>
|
||||
<button className="btn btn-default back" onClick={@_fireMoveToPrevPage}>Back</button>
|
||||
</div>
|
||||
<ReactCSSTransitionGroup transitionName="page">
|
||||
{@_pageComponent()}
|
||||
</ReactCSSTransitionGroup>
|
||||
|
||||
_pageComponent: ->
|
||||
if @state.error
|
||||
|
@ -54,71 +56,53 @@ ContainerView = React.createClass
|
|||
|
||||
if @state.page is 'welcome'
|
||||
<div className="page" key={@state.page}>
|
||||
<h2>Welcome to Edgehill</h2>
|
||||
<div className="thin-container">
|
||||
<button className="btn btn-primary btn-lg btn-block" onClick={=> @_fireMoveToPage('create-account')}>Create an Account</button>
|
||||
<button className="btn btn-primary btn-lg btn-block" onClick={=> @_fireMoveToPage('sign-in')}>Sign In</button>
|
||||
<div className="environment-selector">
|
||||
<h5>Environment</h5>
|
||||
<select value={@state.environment} onChange={@_fireSetEnvironment}>
|
||||
<option value="development">Development (edgehill-dev, api-staging)</option>
|
||||
<option value="staging">Staging (edgehill-staging, api-staging)</option>
|
||||
<option value="production">Production (edgehill, api)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="quit" onClick={@_fireQuit}>
|
||||
<RetinaImg name="onboarding-close.png"/>
|
||||
</div>
|
||||
</div>
|
||||
else if @state.page is 'sign-in'
|
||||
<div className="page" key={@state.page}>
|
||||
<RetinaImg name="onboarding-logo.png" />
|
||||
<h2>Welcome to Nilas</h2>
|
||||
|
||||
<RetinaImg name="onboarding-divider.png" />
|
||||
|
||||
<form role="form" className="thin-container">
|
||||
{alert}
|
||||
<div className="form-group">
|
||||
<input type="email" placeholder="Username" className="form-control" tabIndex="1" value={@state.username} onChange={@_onValueChange} id="username" />
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<input type="password" placeholder="Password" className="form-control" tabIndex="2" value={@state.password} onChange={@_onValueChange} id="password" />
|
||||
</div>
|
||||
<button className="btn btn-primary btn-lg btn-block" onClick={@_fireSignIn}>Sign In</button>
|
||||
</form>
|
||||
</div>
|
||||
else if @state.page == 'create-account'
|
||||
<div className="page" key={@state.page}>
|
||||
<form role="form" className="thin-container">
|
||||
{alert}
|
||||
<div className="form-group">
|
||||
<input type="text" placeholder="First Name" className="form-control" tabIndex="1" value={@state.first_name} onChange={@_onValueChange} id="first_name" />
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<input type="text" placeholder="Last Name" className="form-control" tabIndex="2" value={@state.last_name} onChange={@_onValueChange} id="last_name" />
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<input type="text" placeholder="Email Address" className="form-control" tabIndex="3" value={@state.email} onChange={@_onValueChange} id="email" />
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<input type="email" placeholder="Username" className="form-control" tabIndex="4" value={@state.username} onChange={@_onValueChange} id="username" />
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<input type="password" placeholder="Password" className="form-control" tabIndex="5" value={@state.password} onChange={@_onValueChange} id="password" />
|
||||
</div>
|
||||
<button className="btn btn-primary btn-lg btn-block" onClick={@_fireCreateAccount}>Create Account</button>
|
||||
<div className="prompt">Enter your email address:</div>
|
||||
<input className="input-bordered" type="email" placeholder="you@gmail.com" tabIndex="1" value={@state.email} onChange={@_onValueChange} id="email" />
|
||||
<button className="btn btn-larger btn-gradient" style={width:215} onClick={@_fireStart}>Start using Nilas</button>
|
||||
{@_environmentComponent()}
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
else if @state.page == 'add-account'
|
||||
<div className="page" key={@state.page}>
|
||||
<h2>Connect an Account</h2>
|
||||
<p>Link accounts from other services to supercharge your email.</p>
|
||||
<div className="thin-container">
|
||||
<button className="btn btn-primary btn-lg btn-block" onClick={=> @_fireAuthAccount('salesforce')}>Salesforce</button>
|
||||
<button className="btn btn-primary btn-lg btn-block" onClick={=> @_fireAuthAccount('linkedin')}>LinkedIn</button>
|
||||
<div className="quit" onClick={@_fireDismiss}>
|
||||
<RetinaImg name="onboarding-close.png"/>
|
||||
</div>
|
||||
<RetinaImg name="onboarding-logo.png" />
|
||||
<h2>Connect an Account</h2>
|
||||
|
||||
<RetinaImg name="onboarding-divider.png" />
|
||||
|
||||
<form role="form" className="thin-container">
|
||||
<div className="prompt">Link accounts from other services to supercharge your email.</div>
|
||||
<button className="btn btn-larger btn-gradient" onClick={=> @_fireAuthAccount('salesforce')}>Salesforce</button>
|
||||
<button className="btn btn-larger btn-gradient" onClick={=> @_fireAuthAccount('linkedin')}>LinkedIn</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
else if @state.page == 'add-account-auth'
|
||||
React.createElement('webview',{
|
||||
"ref": "connect-iframe",
|
||||
"key": this.state.page,
|
||||
"src": this._connectWebViewURL()
|
||||
});
|
||||
<div>
|
||||
{
|
||||
React.createElement('webview',{
|
||||
"ref": "connect-iframe",
|
||||
"key": this.state.page,
|
||||
"src": this._connectWebViewURL()
|
||||
});
|
||||
}
|
||||
<div className="back" onClick={@_fireMoveToPrevPage}>
|
||||
<RetinaImg name="onboarding-back.png"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
else if @state.page == 'add-account-success'
|
||||
# http://codepen.io/stevenfabre/pen/NPWeVb
|
||||
|
@ -129,7 +113,16 @@ ContainerView = React.createClass
|
|||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
_environmentComponent: ->
|
||||
return [] unless atom.inDevMode()
|
||||
<div className="environment-selector">
|
||||
<select value={@state.environment} onChange={@_fireSetEnvironment}>
|
||||
<option value="development">Development (edgehill-dev, api-staging)</option>
|
||||
<option value="staging">Staging (edgehill-staging, api-staging)</option>
|
||||
<option value="production">Production (edgehill, api)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
_connectWebViewURL: ->
|
||||
EdgehillAPI.urlForConnecting(@state.connectType, @state.email)
|
||||
|
@ -146,11 +139,14 @@ ContainerView = React.createClass
|
|||
atom.close()
|
||||
|
||||
_fireQuit: ->
|
||||
require('remote').require('app').quit()
|
||||
require('ipc').send('command', 'application:quit')
|
||||
|
||||
_fireSetEnvironment: (event) ->
|
||||
OnboardingActions.setEnvironment(event.target.value)
|
||||
|
||||
_fireStart: (e) ->
|
||||
OnboardingActions.startConnect('inbox')
|
||||
|
||||
_fireAuthAccount: (service) ->
|
||||
OnboardingActions.startConnect(service)
|
||||
|
||||
|
@ -160,10 +156,3 @@ ContainerView = React.createClass
|
|||
_fireMoveToPrevPage: ->
|
||||
OnboardingActions.moveToPreviousPage()
|
||||
|
||||
_fireSignIn: (e) ->
|
||||
e.preventDefault()
|
||||
OnboardingActions.signIn(@state)
|
||||
|
||||
_fireCreateAccount: (e) ->
|
||||
e.preventDefault()
|
||||
OnboardingActions.createAccount(@state)
|
||||
|
|
|
@ -2,8 +2,6 @@ Reflux = require 'reflux'
|
|||
|
||||
actions = [
|
||||
"setEnvironment",
|
||||
"createAccount",
|
||||
"signIn",
|
||||
"authErrorOccurred",
|
||||
"startConnect",
|
||||
"finishedConnect",
|
||||
|
|
|
@ -3,23 +3,24 @@ Actions = require './onboarding-actions'
|
|||
{EdgehillAPI} = require 'inbox-exports'
|
||||
ipc = require 'ipc'
|
||||
|
||||
if atom.state.mode isnt "onboarding" and atom.state.mode isnt "spec" then return
|
||||
|
||||
module.exports =
|
||||
OnboardingStore = Reflux.createStore
|
||||
init: ->
|
||||
@_error = ''
|
||||
@_page = atom.getLoadSettings().page || 'welcome'
|
||||
|
||||
@_pageStack = [@_page]
|
||||
|
||||
defaultEnv = if atom.inDevMode() then 'staging' else 'production'
|
||||
atom.config.set('inbox.env', defaultEnv) unless atom.config.get('inbox.env')
|
||||
atom.config.set('env', defaultEnv) unless atom.config.get('env')
|
||||
|
||||
@listenTo Actions.setEnvironment, @_onSetEnvironment
|
||||
@listenTo Actions.moveToPreviousPage, @_onMoveToPreviousPage
|
||||
@listenTo Actions.moveToPage, @_onMoveToPage
|
||||
@listenTo Actions.startConnect, @_onStartConnect
|
||||
@listenTo Actions.finishedConnect, @_onFinishedConnect
|
||||
@listenTo Actions.createAccount, @_onCreateAccount
|
||||
@listenTo Actions.signIn, @_onSignIn
|
||||
|
||||
page: ->
|
||||
@_page
|
||||
|
@ -28,7 +29,7 @@ OnboardingStore = Reflux.createStore
|
|||
@_error
|
||||
|
||||
environment: ->
|
||||
atom.config.get('inbox.env')
|
||||
atom.config.get('env')
|
||||
|
||||
connectType: ->
|
||||
@_connectType
|
||||
|
@ -44,37 +45,6 @@ OnboardingStore = Reflux.createStore
|
|||
@_page = page
|
||||
@trigger()
|
||||
|
||||
_onSignIn: (fields) ->
|
||||
@_error = null
|
||||
@trigger()
|
||||
|
||||
EdgehillAPI.signIn(fields)
|
||||
.then (user) =>
|
||||
if atom.config.get('inbox.token')
|
||||
@_onMoveToPage('add-account-success')
|
||||
setTimeout ->
|
||||
# Important: This delay is actually necessary, because
|
||||
# atom.config changes are not persisted instantly.
|
||||
ipc.send('onboarding-complete')
|
||||
atom.close()
|
||||
, 2500
|
||||
else
|
||||
@_onStartConnect('inbox')
|
||||
.catch (err) =>
|
||||
@_error = err
|
||||
@trigger()
|
||||
|
||||
_onCreateAccount: (fields) ->
|
||||
@_error = null
|
||||
@trigger()
|
||||
|
||||
EdgehillAPI.createAccount(fields)
|
||||
.then =>
|
||||
@_onStartConnect('inbox')
|
||||
.catch (err) =>
|
||||
@_error = err
|
||||
@trigger()
|
||||
|
||||
_onStartConnect: (service) ->
|
||||
@_connectType = service
|
||||
@_onMoveToPage('add-account-auth')
|
||||
|
@ -90,5 +60,5 @@ OnboardingStore = Reflux.createStore
|
|||
|
||||
_onSetEnvironment: (env) ->
|
||||
throw new Error("Environment #{env} is not allowed") unless env in ['development', 'staging', 'production']
|
||||
atom.config.set('inbox.env', env)
|
||||
atom.config.set('env', env)
|
||||
@trigger()
|
||||
|
|
|
@ -22,101 +22,92 @@
|
|||
.onboarding-container {
|
||||
width:100%;
|
||||
height:100%;
|
||||
background-color: #f0f0f0;
|
||||
-webkit-animation: fadein 0.8s;
|
||||
-webkit-user-select:none;
|
||||
text-align: center;
|
||||
|
||||
h2 {
|
||||
padding:0;
|
||||
margin:0;
|
||||
}
|
||||
h2, p {
|
||||
text-align: center;
|
||||
}
|
||||
iframe, webview {
|
||||
position: absolute;
|
||||
width:100%;
|
||||
height:100%;
|
||||
position: absolute;
|
||||
left:0;
|
||||
top:0;
|
||||
border:0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 27px;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
.prompt {
|
||||
color:#5D5D5D;
|
||||
font-size:1.07em;
|
||||
font-weight:300;
|
||||
margin-top:20px;
|
||||
margin-bottom:14px;
|
||||
}
|
||||
|
||||
form {
|
||||
padding-right:25px;
|
||||
padding-left:25px;
|
||||
}
|
||||
|
||||
input {
|
||||
display:block;
|
||||
padding:10px;
|
||||
width:100%;
|
||||
margin-bottom:20px;
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
.environment-selector {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
width:100%;
|
||||
border-top:1px solid @border-color-divider;
|
||||
text-align: center;
|
||||
|
||||
h5 {
|
||||
text-align: center;
|
||||
position: relative;
|
||||
top: -18px;
|
||||
background-color: white;
|
||||
display: inline-block;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
margin-bottom: 0;
|
||||
height: 10px;
|
||||
}
|
||||
opacity:0.1;
|
||||
top: 224px;
|
||||
width:292px;
|
||||
select {
|
||||
position: relative;
|
||||
top: -14px;
|
||||
width:100%;
|
||||
}
|
||||
}
|
||||
.thin-container {
|
||||
margin:auto;
|
||||
padding-top:40px;
|
||||
width:250px;
|
||||
position: relative;
|
||||
height:100%;
|
||||
}
|
||||
|
||||
.page {
|
||||
position:absolute;
|
||||
top:0;
|
||||
width:100%;
|
||||
height:100%;
|
||||
padding:40px;
|
||||
padding-top:15%;
|
||||
}
|
||||
.add-account .back,
|
||||
.welcome .back {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.quit, .dismiss {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.add-account .dismiss,
|
||||
.welcome .quit {
|
||||
display:inherit;
|
||||
}
|
||||
|
||||
.back, .dismiss, .quit {
|
||||
.quit {
|
||||
position: absolute;
|
||||
top:10px;
|
||||
left:10px;
|
||||
top:5px;
|
||||
left:5px;
|
||||
}
|
||||
|
||||
.back,
|
||||
.dismiss {
|
||||
position: absolute;
|
||||
top:25px;
|
||||
left:25px;
|
||||
}
|
||||
|
||||
.page-enter {
|
||||
opacity: 0.01;
|
||||
transform: translateY(20px);
|
||||
transition: all .3s ease-out;
|
||||
}
|
||||
|
||||
.page-enter.page-enter-active {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
.page-leave {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
transition: all .3s ease-in;
|
||||
}
|
||||
|
||||
.page-leave.page-leave-active {
|
||||
opacity: 0.01;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
|
||||
.check {
|
||||
|
|
|
@ -25,6 +25,7 @@ SearchBar = React.createClass
|
|||
render: ->
|
||||
inputValue = @_queryToString(@state.query)
|
||||
inputClass = React.addons.classSet
|
||||
'input-bordered': true
|
||||
'empty': inputValue.length is 0
|
||||
|
||||
headerComponents = [
|
||||
|
@ -93,6 +94,8 @@ SearchBar = React.createClass
|
|||
|
||||
_onValueChange: (event) ->
|
||||
Actions.searchQueryChanged(@_stringToQuery(event.target.value))
|
||||
if (event.target.value is '')
|
||||
@_onClearSearch()
|
||||
|
||||
_onSelectSuggestion: (item) ->
|
||||
Actions.searchQueryCommitted(item.value)
|
||||
|
|
|
@ -65,7 +65,10 @@
|
|||
position: relative;
|
||||
|
||||
&.showing-suggestions {
|
||||
.suggestions{ display: inherit; }
|
||||
.suggestions { display: inherit; }
|
||||
}
|
||||
&.showing-query {
|
||||
.clear { display: inherit; }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,11 +82,10 @@
|
|||
|
||||
&.clear {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
top: floor(40px - 26px)/2;
|
||||
color: @input-accessory-color;
|
||||
right: @padding-base-horizontal;
|
||||
display: none;
|
||||
padding: 17px 19px;
|
||||
line-height: 20px
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,29 +1,17 @@
|
|||
_ = require 'underscore-plus'
|
||||
React = require "react"
|
||||
SidebarFullContact = require "./sidebar-fullcontact.cjsx"
|
||||
|
||||
{ComponentRegistry} = require("inbox-exports")
|
||||
|
||||
module.exports =
|
||||
item: null
|
||||
|
||||
activate: (@state={}) ->
|
||||
unless @item?
|
||||
@item = document.createElement("div")
|
||||
@item.setAttribute("id", "sidebar-fullcontact")
|
||||
@item.setAttribute("class", "sidebar-fullcontact")
|
||||
|
||||
atom.workspace.addColumnItem(@item, "message-and-composer")
|
||||
|
||||
ComponentRegistry.register
|
||||
name: 'SidebarFullContact'
|
||||
view: SidebarFullContact
|
||||
|
||||
React.render(<SidebarFullContact />, @item)
|
||||
ComponentRegistry.register
|
||||
name: 'SidebarFullContact'
|
||||
view: SidebarFullContact
|
||||
|
||||
deactivate: ->
|
||||
React.unmountComponentAtNode(@item)
|
||||
@item.remove()
|
||||
@item = null
|
||||
ComponentRegistry.unregister('SidebarFullContact')
|
||||
|
||||
serialize: -> @state
|
||||
|
|
|
@ -1,42 +1,24 @@
|
|||
# Email-specific core key-mappings
|
||||
# All platforms are put here to consolidate custom actions and to prevent
|
||||
# duplication in 3 files.
|
||||
#
|
||||
# TODO let the user pick whether they want to use Gmail, Mac Mail, or
|
||||
# Outlook keymappings
|
||||
# There are additional mappings in <platform>.cson files that bind
|
||||
# menu items. In the future, we should break these into files like:
|
||||
# darwin-gmail.cson, darwin-macmail.cson, win32-gmail.cson...
|
||||
|
||||
'body':
|
||||
'c' : 'application:new-message' # Gmail
|
||||
'cmd-n' : 'application:new-message' # Mac mail
|
||||
'ctrl-n': 'application:new-message' # Outlook
|
||||
|
||||
'k' : 'application:previous-message' # Gmail
|
||||
'up': 'application:previous-message' # Mac mail
|
||||
|
||||
'j' : 'application:next-message' # Gmail
|
||||
'down': 'application:next-message' # Mac mail
|
||||
|
||||
'c' : 'application:new-message' # Gmail
|
||||
'k' : 'application:previous-message' # Gmail
|
||||
'up' : 'application:previous-message' # Mac mail
|
||||
'j' : 'application:next-message' # Gmail
|
||||
'down' : 'application:next-message' # Mac mail
|
||||
']' : 'application:archive-and-previous' # Gmail
|
||||
|
||||
'[' : 'application:archive-thread' # Gmail
|
||||
'e' : 'application:archive-thread' # Gmail
|
||||
'delete' : 'application:archive-thread' # Mac mail
|
||||
'backspace': 'application:archive-thread' # Outlook
|
||||
|
||||
'r' : 'application:reply' # Gmail
|
||||
'cmd-r' : 'application:reply' # Mac mail
|
||||
'ctrl-r': 'application:reply' # Outlook
|
||||
|
||||
'a' : 'application:reply-all' # Gmail
|
||||
'cmd-R' : 'application:reply-all' # Mac mail
|
||||
'ctrl-R': 'application:reply-all' # Outlook
|
||||
|
||||
'f' : 'application:forward' # Gmail
|
||||
'cmd-F' : 'application:forward' # Mac mail
|
||||
'ctrl-F': 'application:forward' # Outlook
|
||||
|
||||
'cmd-alt-f': 'application:focus-search' # Mac mail
|
||||
|
||||
'cmd-D': 'application:send-message' # Mac mail
|
||||
|
||||
# Default cross-platform core behaviors
|
||||
'left': 'core:move-left'
|
||||
|
@ -53,7 +35,8 @@
|
|||
'shift-delete': 'core:cut'
|
||||
|
||||
# Inputs are native by default.
|
||||
'body input, body textarea, body *[contenteditable]':
|
||||
# Also make sure not to catch anything intended for a webview
|
||||
'body input, body textarea, body *[contenteditable], body webview':
|
||||
'up': 'native!'
|
||||
'left': 'native!'
|
||||
'down': 'native!'
|
||||
|
@ -79,8 +62,6 @@
|
|||
'cmd-enter': 'native!'
|
||||
'ctrl-enter': 'native!'
|
||||
'shift-enter': 'native!'
|
||||
'tab': 'core:focus-next'
|
||||
'shift-tab': 'core:focus-previous'
|
||||
'backspace': 'native!'
|
||||
'shift-backspace': 'native!'
|
||||
'delete': 'native!'
|
||||
|
@ -207,6 +188,16 @@
|
|||
'?': 'native!'
|
||||
'/': 'native!'
|
||||
|
||||
'body input, body textarea, body *[contenteditable]':
|
||||
'tab': 'core:focus-next'
|
||||
'shift-tab': 'core:focus-previous'
|
||||
|
||||
'body webview':
|
||||
'tab': 'native!'
|
||||
'shift-tab': 'native!'
|
||||
|
||||
|
||||
|
||||
# For menus
|
||||
'body .menu, body .menu, body .menu input':
|
||||
'up': 'menu:move-up'
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
# Note: For a menu item to have a keyboard equiavalent, it needs
|
||||
# to be listed in this file.
|
||||
|
||||
# Mac application keys
|
||||
'body':
|
||||
# Mac email-specific menu items
|
||||
'cmd-n' : 'application:new-message' # Mac mail
|
||||
'cmd-r' : 'application:reply' # Mac mail
|
||||
'cmd-R' : 'application:reply-all' # Mac mail
|
||||
'cmd-F' : 'application:forward' # Mac mail
|
||||
'cmd-alt-f': 'application:focus-search' # Mac mail
|
||||
'cmd-D': 'application:send-message' # Mac mail
|
||||
|
||||
# Mac application keys
|
||||
'cmd-q': 'application:quit'
|
||||
'cmd-h': 'application:hide'
|
||||
'cmd-1': 'application:show-main-window'
|
||||
|
@ -11,7 +19,7 @@
|
|||
'alt-cmd-ctrl-m': 'application:zoom'
|
||||
'cmd-alt-ctrl-s': 'application:run-all-specs'
|
||||
|
||||
# Mac core keys
|
||||
# Mac core keys
|
||||
'cmd-z': 'core:undo'
|
||||
'cmd-Z': 'core:redo'
|
||||
'cmd-y': 'core:redo'
|
||||
|
@ -20,7 +28,7 @@
|
|||
'cmd-a': 'core:select-all'
|
||||
'cmd-v': 'core:paste'
|
||||
|
||||
# Mac window keys
|
||||
# Mac window keys
|
||||
'cmd-w': 'window:close'
|
||||
'cmd-=': 'window:increase-font-size'
|
||||
'cmd-+': 'window:increase-font-size'
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
# Note: For a menu item to have a keyboard equiavalent, it needs
|
||||
# to be listed in this file.
|
||||
|
||||
# Linux application keys
|
||||
# Linux email-specific menu items
|
||||
'body':
|
||||
'ctrl-n': 'application:new-message' # Outlook
|
||||
'ctrl-r': 'application:reply' # Outlook
|
||||
'ctrl-R': 'application:reply-all' # Outlook
|
||||
'ctrl-F': 'application:forward' # Outlook
|
||||
|
||||
# Linux application keys
|
||||
'ctrl-q': 'application:quit'
|
||||
'ctrl-alt-s': 'application:run-all-specs'
|
||||
|
||||
# Linux core keys
|
||||
# Linux core keys
|
||||
'ctrl-z': 'core:undo'
|
||||
'ctrl-Z': 'core:redo'
|
||||
'ctrl-y': 'core:redo'
|
||||
|
@ -17,7 +23,7 @@
|
|||
'ctrl-insert': 'core:copy'
|
||||
'shift-insert': 'core:paste'
|
||||
|
||||
# Linux window keys
|
||||
# Linux window keys
|
||||
'ctrl-w': 'core:close'
|
||||
'ctrl-=': 'window:increase-font-size'
|
||||
'ctrl-+': 'window:increase-font-size'
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
# Note: For a menu item to have a keyboard equiavalent, it needs
|
||||
# to be listed in this file.
|
||||
|
||||
# Windows application keys
|
||||
'body':
|
||||
# Windows email-specific menu items
|
||||
'ctrl-n': 'application:new-message' # Outlook
|
||||
'ctrl-r': 'application:reply' # Outlook
|
||||
'ctrl-R': 'application:reply-all' # Outlook
|
||||
'ctrl-F': 'application:forward' # Outlook
|
||||
|
||||
# Windows application keys
|
||||
'ctrl-q': 'application:quit'
|
||||
'ctrl-alt-s': 'application:run-all-specs'
|
||||
|
||||
|
|
|
@ -84,7 +84,6 @@
|
|||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"preinstall": "node -e 'process.exit(0)'",
|
||||
"postinstall": "(cd internal_packages/composer; npm install)"
|
||||
"preinstall": "node -e 'process.exit(0)'"
|
||||
}
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 361 KiB After Width: | Height: | Size: 361 KiB |
Before Width: | Height: | Size: 274 KiB After Width: | Height: | Size: 19 KiB |
BIN
resources/win/loading.png
Normal file
After Width: | Height: | Size: 196 KiB |
|
@ -124,7 +124,7 @@ function bootstrap() {
|
|||
options: semverOptions
|
||||
},
|
||||
{
|
||||
command: 'build/node_modules/.bin/grunt download-atom-shell --gruntfile build/Gruntfile.coffee',
|
||||
command: 'grunt download-atom-shell --gruntfile ./build/Gruntfile.coffee',
|
||||
message: m7
|
||||
}
|
||||
];
|
||||
|
|
|
@ -14,7 +14,6 @@ KeymapManager = require '../src/keymap-extensions'
|
|||
{$} = require '../src/space-pen-extensions'
|
||||
|
||||
Config = require '../src/config'
|
||||
Workspace = require '../src/workspace-edgehill'
|
||||
ServiceHub = require 'service-hub'
|
||||
pathwatcher = require 'pathwatcher'
|
||||
clipboard = require 'clipboard'
|
||||
|
@ -97,12 +96,10 @@ beforeEach ->
|
|||
|
||||
$.fx.off = true
|
||||
documentTitle = null
|
||||
atom.workspace = new Workspace()
|
||||
atom.packages.serviceHub = new ServiceHub
|
||||
atom.keymaps.keyBindings = _.clone(keyBindingsToRestore)
|
||||
atom.commands.restoreSnapshot(commandsToRestore)
|
||||
atom.styles.restoreSnapshot(styleElementsToRestore)
|
||||
|
||||
atom.workspaceViewParentSelector = '#jasmine-content'
|
||||
|
||||
window.resetTimeouts()
|
||||
|
@ -164,10 +161,6 @@ afterEach ->
|
|||
atom.menu.template = []
|
||||
atom.contextMenu.clear()
|
||||
|
||||
atom.workspace?.destroy()
|
||||
atom.workspace = null
|
||||
delete atom.state.workspace
|
||||
|
||||
atom.themes.removeStylesheet('global-editor-styles')
|
||||
|
||||
delete atom.state.packageStates
|
||||
|
|
|
@ -210,6 +210,14 @@ class Atom extends Model
|
|||
|
||||
@keymaps = new KeymapManager({configDirPath, resourcePath})
|
||||
@keymaps.subscribeToFileReadFailure()
|
||||
@keymaps.onDidMatchBinding (event) ->
|
||||
# If the user fired a command with the application: prefix bound to the body, re-fire it
|
||||
# up into the browser process. This prevents us from needing this crap, which has to be
|
||||
# updated every time a new application: command is added:
|
||||
# https://github.com/atom/atom/blob/master/src/workspace-element.coffee#L119
|
||||
if event.binding.command.indexOf('application:') is 0 and event.binding.selector is "body"
|
||||
ipc.send('command', event.binding.command)
|
||||
|
||||
@tooltips = new TooltipManager
|
||||
@notifications = new NotificationManager
|
||||
@commands = new CommandRegistry
|
||||
|
@ -357,6 +365,9 @@ class Atom extends Model
|
|||
isReleasedVersion: ->
|
||||
not /\w{7}/.test(@getVersion()) # Check if the release is a 7-character SHA prefix
|
||||
|
||||
isLoggedIn: ->
|
||||
atom.config.get('inbox.token')
|
||||
|
||||
# Public: Get the directory path to Atom's configuration area.
|
||||
#
|
||||
# Returns the absolute path to `~/.atom`.
|
||||
|
@ -509,6 +520,7 @@ class Atom extends Model
|
|||
width > 0 and height > 0 and x + width > 0 and y + height > 0
|
||||
|
||||
storeDefaultWindowDimensions: ->
|
||||
return unless @mode is 'editor'
|
||||
dimensions = @getWindowDimensions()
|
||||
if @isValidDimensions(dimensions)
|
||||
localStorage.setItem("defaultWindowDimensions", JSON.stringify(dimensions))
|
||||
|
@ -564,17 +576,17 @@ class Atom extends Model
|
|||
@requireUserInitScript() unless safeMode
|
||||
@menu.update()
|
||||
|
||||
@commands.add 'atom-workspace',
|
||||
'atom-workspace:add-account': =>
|
||||
@displayOnboardingWindow('add-account')
|
||||
'atom-workspace:logout': =>
|
||||
@logout() if @isLoggedIn()
|
||||
|
||||
ipc.on 'onboarding-complete', =>
|
||||
maximize = dimensions?.maximized and process.platform isnt 'darwin'
|
||||
@displayWindow({maximize})
|
||||
|
||||
@commands.add 'atom-workspace',
|
||||
'atom-workspace:logout': => @logout()
|
||||
|
||||
@commands.add 'atom-workspace',
|
||||
'atom-workspace:add-account': => @displayOnboardingWindow('add-account')
|
||||
|
||||
if atom.config.get('inbox.token')
|
||||
if @isLoggedIn()
|
||||
maximize = dimensions?.maximized and process.platform isnt 'darwin'
|
||||
@displayWindow({maximize})
|
||||
else
|
||||
|
@ -583,24 +595,22 @@ class Atom extends Model
|
|||
# Call this method when establishing a secondary application window
|
||||
# displaying a specific set of packages.
|
||||
startSecondaryWindow: (packages = []) ->
|
||||
{resourcePath, safeMode} = @getLoadSettings()
|
||||
{resourcePath, safeMode, width, height} = @getLoadSettings()
|
||||
|
||||
@loadConfig()
|
||||
@inbox.APIToken = atom.config.get('inbox.token')
|
||||
|
||||
@keymaps.loadBundledKeymaps()
|
||||
@themes.loadBaseStylesheets()
|
||||
|
||||
Workspace = require './workspace-edgehill'
|
||||
Actions = require './flux/actions'
|
||||
|
||||
@workspace = new Workspace
|
||||
@keymaps.loadUserKeymap()
|
||||
|
||||
for pack in packages
|
||||
@packages.loadPackage(pack)
|
||||
@packages.activate()
|
||||
@keymaps.loadUserKeymap()
|
||||
|
||||
@setWindowDimensions({width, height}) if width and height
|
||||
|
||||
@menu.update()
|
||||
@subscribe @config.onDidChange 'core.autoHideMenuBar', ({newValue}) =>
|
||||
@setAutoHideMenuBar(newValue)
|
||||
|
@ -621,20 +631,20 @@ class Atom extends Model
|
|||
title: 'Welcome to Edgehill'
|
||||
frame: false
|
||||
page: page
|
||||
width: 340
|
||||
height: 475
|
||||
resizable: false
|
||||
windowName: 'onboarding'
|
||||
windowPackages: ['onboarding']
|
||||
ipc.send('show-secondary-window', options)
|
||||
|
||||
unloadEditorWindow: ->
|
||||
@state.edgehillWorkspace = @workspace.serialize()
|
||||
@packages.deactivatePackages()
|
||||
@state.packageStates = @packages.packageStates
|
||||
@saveSync()
|
||||
@windowState = null
|
||||
|
||||
removeEditorWindow: ->
|
||||
@workspace?.destroy()
|
||||
@workspace = null
|
||||
@windowEventHandler?.unsubscribe()
|
||||
|
||||
###
|
||||
|
@ -715,19 +725,16 @@ class Atom extends Model
|
|||
###
|
||||
|
||||
deserializeWorkspaceView: ->
|
||||
# Put state back into store
|
||||
startTime = Date.now()
|
||||
Workspace = require './workspace-edgehill'
|
||||
#@workspace = Workspace.deserialize(@state.edgehillWorkspace) ? new Workspace
|
||||
@workspace = new Workspace
|
||||
# Put state back into sheet-container? Restore app state here
|
||||
@deserializeTimings.workspace = Date.now() - startTime
|
||||
|
||||
SheetContainer = require './sheet-container'
|
||||
@item = document.createElement("div")
|
||||
@item = document.createElement("atom-workspace")
|
||||
@item.setAttribute("id", "sheet-container")
|
||||
@item.setAttribute("class", "sheet-container")
|
||||
|
||||
React = require "react"
|
||||
SheetContainer = require './sheet-container'
|
||||
React.render(React.createElement(SheetContainer), @item)
|
||||
document.querySelector(@workspaceViewParentSelector).appendChild(@item)
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ class AtomWindow
|
|||
isSpec: null
|
||||
|
||||
constructor: (settings={}) ->
|
||||
{@resourcePath, pathToOpen, initialLine, initialColumn, @neverClose, @isSpec, @exitWhenDone, @safeMode, @devMode, frame, title} = settings
|
||||
{@resourcePath, pathToOpen, initialLine, initialColumn, @neverClose, @isSpec, @exitWhenDone, @safeMode, @devMode, frame, title, resizable} = settings
|
||||
|
||||
# Normalize to make sure drive letter case is consistent on Windows
|
||||
@resourcePath = path.normalize(@resourcePath) if @resourcePath
|
||||
|
@ -27,10 +27,12 @@ class AtomWindow
|
|||
show: false
|
||||
title: title ? 'Edgehill'
|
||||
frame: frame ? true
|
||||
resizable: resizable ? true
|
||||
icon: @constructor.iconPath
|
||||
'web-preferences':
|
||||
'direct-write': true
|
||||
'subpixel-font-scaling': false
|
||||
|
||||
# Don't set icon on Windows so the exe's ico will be used as window and
|
||||
# taskbar's icon. See https://github.com/atom/atom/issues/4811 for more.
|
||||
if process.platform is 'linux'
|
||||
|
|
|
@ -13,6 +13,7 @@ Flexbox = React.createClass
|
|||
render: ->
|
||||
style = _.extend (@props.style || {}),
|
||||
'flexDirection': @props.direction,
|
||||
'position':'relative'
|
||||
'display': 'flex'
|
||||
'height':'100%'
|
||||
|
||||
|
|
|
@ -8,12 +8,12 @@ async = require 'async'
|
|||
class EdgehillAPI
|
||||
|
||||
constructor: ->
|
||||
atom.config.onDidChange('inbox.env', @_onConfigChanged)
|
||||
atom.config.onDidChange('env', @_onConfigChanged)
|
||||
@_onConfigChanged()
|
||||
@
|
||||
|
||||
_onConfigChanged: =>
|
||||
env = atom.config.get('inbox.env')
|
||||
env = atom.config.get('env')
|
||||
if env is 'development'
|
||||
@APIRoot = "https://edgehill-dev.nilas.com"
|
||||
else if env is 'staging'
|
||||
|
@ -44,49 +44,17 @@ class EdgehillAPI
|
|||
else
|
||||
options.success(body) if options.success
|
||||
|
||||
createAccount: ({first_name, last_name, username, password}, callback) ->
|
||||
new Promise (resolve, reject) =>
|
||||
@request
|
||||
path: '/users'
|
||||
method: 'POST'
|
||||
body:
|
||||
first_name: first_name
|
||||
last_name: last_name
|
||||
username: username
|
||||
password: password
|
||||
success: =>
|
||||
@setCredentials
|
||||
username: username
|
||||
password: password
|
||||
resolve()
|
||||
error: (err) ->
|
||||
reject(err.message)
|
||||
|
||||
signIn: ({username, password}) ->
|
||||
@setCredentials
|
||||
username: username
|
||||
password: password
|
||||
new Promise (resolve, reject) =>
|
||||
@request
|
||||
path: '/users/me'
|
||||
method: 'GET'
|
||||
success: (userJson) =>
|
||||
@addTokens(userJson.tokens)
|
||||
resolve(userJson)
|
||||
error: (err) =>
|
||||
@setCredentials(null)
|
||||
reject(err.message)
|
||||
|
||||
urlForConnecting: (provider, email_address = '') ->
|
||||
auth = @getCredentials()
|
||||
root = @APIRoot.replace('://', "://#{auth.username}:#{auth.password}@")
|
||||
root = @APIRoot
|
||||
root = root.replace('://', "://#{auth.username}:#{auth.password}@") if auth
|
||||
"#{root}/connect/#{provider}?login_hint=#{email_address}"
|
||||
|
||||
getCredentials: ->
|
||||
atom.config.get('inbox.account')
|
||||
atom.config.get('edgehill.credentials')
|
||||
|
||||
setCredentials: (credentials) ->
|
||||
atom.config.set('inbox.account', credentials)
|
||||
atom.config.set('edgehill.credentials', credentials)
|
||||
|
||||
addTokens: (tokens) ->
|
||||
for token in tokens
|
||||
|
@ -94,7 +62,10 @@ class EdgehillAPI
|
|||
atom.config.set('inbox.token', token.access_token)
|
||||
if token.provider is 'salesforce'
|
||||
atom.config.set('salesforce.token', token.access_token)
|
||||
|
||||
|
||||
if token.user_identifier?
|
||||
@setCredentials({username: token.user_identifier, password: ''})
|
||||
|
||||
tokenForProvider: (provider) ->
|
||||
atom.config.get("#{provider}.token")
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ class InboxAPI
|
|||
|
||||
constructor: ->
|
||||
@_streamingConnections = []
|
||||
atom.config.onDidChange('inbox.env', @_onConfigChanged)
|
||||
atom.config.onDidChange('env', @_onConfigChanged)
|
||||
atom.config.onDidChange('inbox.token', @_onConfigChanged)
|
||||
@_onConfigChanged()
|
||||
|
||||
|
@ -24,7 +24,7 @@ class InboxAPI
|
|||
prev = {@APIToken, @AppID, @APIRoot}
|
||||
|
||||
@APIToken = atom.config.get('inbox.token')
|
||||
env = atom.config.get('inbox.env')
|
||||
env = atom.config.get('env')
|
||||
if env in ['production']
|
||||
@AppID = 'c96gge1jo29pl2rebcb7utsbp'
|
||||
@APIRoot = 'https://api.nilas.com'
|
||||
|
@ -83,7 +83,7 @@ class InboxAPI
|
|||
## TODO use OfflineStatusStore
|
||||
Actions.longPollOffline()
|
||||
|
||||
connection.onDeltas (deltas) =>
|
||||
connection.onDeltas (deltas) ->
|
||||
# TODO DO NOT FORGET TO UNCOMMENT ME
|
||||
# @_handleDeltas(deltas)
|
||||
|
||||
|
|
|
@ -86,11 +86,10 @@ class InboxLongConnection
|
|||
@_buffer = bufferJSONs[bufferJSONs.length - 1]
|
||||
|
||||
start: ->
|
||||
return if not @_inbox.APIToken?
|
||||
return if @_state is InboxLongConnection.State.Ended
|
||||
return if @_req
|
||||
|
||||
throw (new Error 'Cannot start polling without auth token.') unless @_inbox.APIToken
|
||||
|
||||
console.log("Long Polling Connection: Starting....")
|
||||
@withCursor (cursor) =>
|
||||
return if @state is InboxLongConnection.State.Ended
|
||||
|
|
|
@ -81,10 +81,15 @@ Utils =
|
|||
[name, ext] = fullname.split('.')
|
||||
|
||||
if Utils.images is undefined
|
||||
start = Date.now()
|
||||
{resourcePath} = atom.getLoadSettings()
|
||||
imagesPath = path.join(resourcePath, 'static', 'images')
|
||||
files = fs.listTreeSync(imagesPath)
|
||||
|
||||
Utils.images = {}
|
||||
files = fs.listTreeSync('./static/images')
|
||||
for file in files
|
||||
Utils.images[path.basename(file)] = file.substr(7)
|
||||
Utils.images[path.basename(file)] = file for file in files
|
||||
# console.log("Loaded image map in #{Date.now()-start}msec")
|
||||
|
||||
if window.devicePixelRatio > 1
|
||||
return Utils.images["#{name}@2x.#{ext}"] ? Utils.images[fullname] ? Utils.images["#{name}@1x.#{ext}"]
|
||||
|
|
|
@ -370,13 +370,15 @@ class ThemeManager
|
|||
isInitialLoadComplete: -> @initialLoadComplete
|
||||
|
||||
addActiveThemeClasses: ->
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
workspaceElement = document.getElementsByTagName('atom-workspace')[0]
|
||||
return unless workspaceElement
|
||||
for pack in @getActiveThemes()
|
||||
workspaceElement.classList.add("theme-#{pack.name}")
|
||||
return
|
||||
|
||||
removeActiveThemeClasses: ->
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
workspaceElement = document.getElementsByTagName('atom-workspace')[0]
|
||||
return unless workspaceElement
|
||||
for pack in @getActiveThemes()
|
||||
workspaceElement.classList.remove("theme-#{pack.name}")
|
||||
return
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
_ = require 'underscore-plus'
|
||||
{Model} = require 'theorist'
|
||||
Q = require 'q'
|
||||
Serializable = require 'serializable'
|
||||
{Emitter, Disposable, CompositeDisposable} = require 'event-kit'
|
||||
WorkspaceElement = require './workspace-element-edgehill'
|
||||
|
||||
# Essential: Represents the state of the user interface for the entire window.
|
||||
# An instance of this class is available via the `atom.workspace` global.
|
||||
#
|
||||
# Interact with this object to open files, be notified of current and future
|
||||
# editors, and manipulate panes. To add panels, you'll need to use the
|
||||
# {WorkspaceView} class for now until we establish APIs at the model layer.
|
||||
#
|
||||
# * `editor` {TextEditor} the new editor
|
||||
#
|
||||
module.exports =
|
||||
class Workspace extends Model
|
||||
atom.deserializers.add(this)
|
||||
Serializable.includeInto(this)
|
||||
|
||||
@properties
|
||||
fullScreen: false
|
||||
|
||||
constructor: (params) ->
|
||||
super
|
||||
@emitter = new Emitter
|
||||
|
||||
atom.views.addViewProvider
|
||||
modelConstructor: Workspace
|
||||
viewConstructor: WorkspaceElement
|
||||
|
||||
# Called by the Serializable mixin during deserialization
|
||||
deserializeParams: (params) ->
|
||||
for packageName in params.packagesWithActiveGrammars ? []
|
||||
atom.packages.getLoadedPackage(packageName)?.loadGrammarsSync()
|
||||
params
|
||||
|
||||
# Called by the Serializable mixin during serialization.
|
||||
serializeParams: ->
|
||||
fullScreen: atom.isFullScreen()
|
||||
|
||||
# Updates the application's title and proxy icon based on whichever file is
|
||||
# open.
|
||||
updateWindowTitle: ->
|
||||
## TODO we might want to put the unread count here in the future.
|
||||
document.title = "Edgehill"
|
||||
atom.setRepresentedFilename("Edgehill")
|
||||
|
||||
confirmClose: ->
|
||||
true
|
||||
|
||||
# A no-op in Edgehill Workspace
|
||||
open: ->
|
||||
|
||||
# Appending Children to the Workspace
|
||||
# ----
|
||||
|
||||
addColumnItem: (item, columnId="") ->
|
||||
|
||||
addRow: (item) ->
|
|
@ -1,73 +0,0 @@
|
|||
ipc = require 'ipc'
|
||||
path = require 'path'
|
||||
{Disposable, CompositeDisposable} = require 'event-kit'
|
||||
Grim = require 'grim'
|
||||
scrollbarStyle = require 'scrollbar-style'
|
||||
{callAttachHooks} = require 'space-pen'
|
||||
|
||||
module.exports =
|
||||
class WorkspaceElement extends HTMLElement
|
||||
|
||||
createdCallback: ->
|
||||
@subscriptions = new CompositeDisposable
|
||||
@initializeContent()
|
||||
@observeScrollbarStyle()
|
||||
|
||||
attachedCallback: ->
|
||||
callAttachHooks(this)
|
||||
@focus()
|
||||
|
||||
detachedCallback: ->
|
||||
@subscriptions.dispose()
|
||||
@model.destroy()
|
||||
|
||||
initializeContent: ->
|
||||
@classList.add 'workspace'
|
||||
@setAttribute 'tabindex', -1
|
||||
|
||||
@horizontalAxis = document.createElement('atom-workspace-axis')
|
||||
@horizontalAxis.classList.add('horizontal')
|
||||
|
||||
@horizontalContainer = document.createElement('div')
|
||||
@horizontalContainer.classList.add('atom-workspace-axis-container')
|
||||
@horizontalContainer.appendChild(@horizontalAxis)
|
||||
|
||||
@verticalAxis = document.createElement('atom-workspace-axis')
|
||||
@verticalAxis.classList.add('vertical')
|
||||
@verticalAxis.appendChild(@horizontalContainer)
|
||||
|
||||
@appendChild(@verticalAxis)
|
||||
|
||||
observeScrollbarStyle: ->
|
||||
@subscriptions.add scrollbarStyle.onValue (style) =>
|
||||
switch style
|
||||
when 'legacy'
|
||||
@classList.remove('scrollbars-visible-when-scrolling')
|
||||
@classList.add("scrollbars-visible-always")
|
||||
when 'overlay'
|
||||
@classList.remove('scrollbars-visible-always')
|
||||
@classList.add("scrollbars-visible-when-scrolling")
|
||||
|
||||
getModel: ->
|
||||
@model
|
||||
|
||||
setModel: (@model) ->
|
||||
|
||||
atom.commands.add 'atom-workspace',
|
||||
'application:show-main-window': -> ipc.send('command', 'application:show-main-window')
|
||||
'application:new-message': -> ipc.send('command', 'application:new-message')
|
||||
'application:about': -> ipc.send('command', 'application:about')
|
||||
'application:run-all-specs': -> ipc.send('command', 'application:run-all-specs')
|
||||
'application:run-benchmarks': -> ipc.send('command', 'application:run-benchmarks')
|
||||
'application:show-settings': -> ipc.send('command', 'application:show-settings')
|
||||
'application:quit': -> ipc.send('command', 'application:quit')
|
||||
'application:hide': -> ipc.send('command', 'application:hide')
|
||||
'application:hide-other-applications': -> ipc.send('command', 'application:hide-other-applications')
|
||||
'application:install-update': -> ipc.send('command', 'application:install-update')
|
||||
'application:unhide-all-applications': -> ipc.send('command', 'application:unhide-all-applications')
|
||||
'application:minimize': -> ipc.send('command', 'application:minimize')
|
||||
'application:zoom': -> ipc.send('command', 'application:zoom')
|
||||
'application:bring-all-windows-to-front': -> ipc.send('command', 'application:bring-all-windows-to-front')
|
||||
'window:run-package-specs': -> ipc.send('run-package-specs', path.join(atom.project.getPath(), 'spec'))
|
||||
|
||||
module.exports = WorkspaceElement = document.registerElement 'atom-workspace', prototype: WorkspaceElement.prototype
|
|
@ -1,3 +1,6 @@
|
|||
@import "ui-variables";
|
||||
@import "ui-mixins";
|
||||
|
||||
// .btn-background (@color, @hover-color, @selected-color, @border-color, @text-color, @text-color-hover) {
|
||||
// @border-shadow: inset 0 0 0 1px @border-color;
|
||||
// @active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
|
||||
|
@ -50,22 +53,18 @@
|
|||
//
|
||||
//
|
||||
.btn {
|
||||
|
||||
border: 0;
|
||||
padding: 0.33em 1em;
|
||||
border-radius: @border-radius-base;
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.21);
|
||||
|
||||
height: auto;
|
||||
line-height: 1;
|
||||
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.21);
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
&:active {
|
||||
cursor: pointer;
|
||||
box-shadow: 0 0 1px rgba(0, 0, 0, 0.21);
|
||||
background-color: darken(@btn-default-bg-color, 9%);
|
||||
box-shadow: 0 -1px 1px rgba(0, 0, 0, 0.21);
|
||||
}
|
||||
&:focus {
|
||||
outline: none
|
||||
|
@ -80,9 +79,11 @@
|
|||
}
|
||||
&.btn-large {
|
||||
font-size: @font-size-large;
|
||||
padding: 0.5em 1.3em;
|
||||
}
|
||||
&.btn-larger {
|
||||
font-size: @font-size-larger;
|
||||
padding: 0.66em 1.6em;
|
||||
}
|
||||
|
||||
color: @btn-default-text-color;
|
||||
|
@ -101,35 +102,42 @@
|
|||
}
|
||||
}
|
||||
|
||||
// .btn-icon {
|
||||
// background: transparent;
|
||||
// border: 0;
|
||||
// color: @text-color-subtle;
|
||||
// margin-right: 10px;
|
||||
// outline: none !important;
|
||||
// font-size: 20px;
|
||||
//
|
||||
// &:last-child {
|
||||
// margin-right: 0;
|
||||
// }
|
||||
//
|
||||
// &.inverse {
|
||||
// color: @text-color-inverse;
|
||||
//
|
||||
// &:hover {
|
||||
// color: white;
|
||||
// }
|
||||
//
|
||||
// &:active {
|
||||
// color: @text-color-inverse;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// &:hover {
|
||||
// cursor: pointer;
|
||||
// color: @text-color-link;
|
||||
// }
|
||||
// &:active {
|
||||
// color: darken(@text-color-link, 5%);
|
||||
// }
|
||||
// }
|
||||
.btn-gradient {
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(@btn-default-bg-color), to(darken(@btn-default-bg-color, 4.5%)));
|
||||
}
|
||||
.btn-gradient:active {
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(darken(@btn-default-bg-color, 9%)), to(darken(@btn-default-bg-color, 13.5%)));
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
background: transparent;
|
||||
border: 0;
|
||||
color: @text-color-subtle;
|
||||
margin-right: 10px;
|
||||
outline: none !important;
|
||||
font-size: 20px;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&.inverse {
|
||||
color: @text-color-inverse;
|
||||
|
||||
&:hover {
|
||||
color: white;
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: @text-color-inverse;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: @text-color-link;
|
||||
}
|
||||
&:active {
|
||||
color: @text-color-link-active;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,6 +72,9 @@
|
|||
min-width: 5em;
|
||||
background-color:transparent;
|
||||
}
|
||||
input:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
BIN
static/images/onboarding/onboarding-back@2x.png
Normal file
After Width: | Height: | Size: 205 KiB |
BIN
static/images/onboarding/onboarding-close@2x.png
Normal file
After Width: | Height: | Size: 206 KiB |
BIN
static/images/onboarding/onboarding-divider@2x.png
Normal file
After Width: | Height: | Size: 205 KiB |
BIN
static/images/onboarding/onboarding-logo@2x.png
Normal file
After Width: | Height: | Size: 213 KiB |
|
@ -1,10 +1,23 @@
|
|||
input[type="text"] {
|
||||
@import "ui-variables";
|
||||
@import "ui-mixins";
|
||||
|
||||
input[type="text"],
|
||||
input[type="email"] {
|
||||
width: 100%;
|
||||
padding-left: @padding-xs-horizontal;
|
||||
padding-right: @padding-xs-horizontal;
|
||||
font-size: @font-size-base;
|
||||
line-height: @line-height-computed;
|
||||
border-radius: @border-radius-base;
|
||||
border: 1px solid @input-border;
|
||||
font-weight:400;
|
||||
|
||||
&.input-bordered {
|
||||
border-radius: @border-radius-base;
|
||||
border: 1px solid @input-border;
|
||||
}
|
||||
}
|
||||
input[type="text"]:focus,
|
||||
input[type="email"]:focus, {
|
||||
&.input-bordered {
|
||||
box-shadow: 0 0 3px @accent-primary;
|
||||
}
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
@import "ui-variables";
|
||||
|
||||
// A Mixin holding common UI elements.
|
||||
|
||||
// A box to hold counts of things (like number of items in a tag, or
|
||||
|
|
6
static/normalize.less
vendored
|
@ -94,12 +94,6 @@ audio:not([controls]) {
|
|||
height: 0;
|
||||
}
|
||||
|
||||
// * Address `[hidden]` styling not present in IE 8/9/10.
|
||||
// * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
|
||||
[hidden],
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Links ==========================================================================
|
||||
// * Remove the gray background color from active links in IE 10.
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
@import "ui-variables";
|
||||
@import "ui-mixins";
|
||||
|
||||
//
|
||||
// Typography
|
||||
// --------------------------------------------------
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
@import "ui-variables";
|
||||
@import "ui-mixins";
|
||||
|
||||
:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Color abstraction heirarcy:
|
||||
// Color abstraction hierarchy:
|
||||
// 1. Hex code (#428bca)
|
||||
// 2. Common color name (@blue)
|
||||
// 3. Generic color descriptor (@accent-primary, @background-primary)
|
||||
|
@ -6,7 +6,7 @@
|
|||
// 4. Generic usage descriptor (@input-background, @button-background)
|
||||
// 5. Application-specific usage (@unread-label-background)
|
||||
|
||||
// Typography abstraction heirarcy
|
||||
// Typography abstraction hierarchy
|
||||
// 1. Font-face (FaktPro)
|
||||
// 2. Common name (@bold, @italic)
|
||||
// 3. Generic font descriptor mixins (.bold, .italic, .h1, .h2)
|
||||
|
@ -386,6 +386,10 @@
|
|||
|
||||
/////
|
||||
|
||||
// -------------
|
||||
// EVERYTHING BELOW THIS NEEDS TO BE DEPRECATED OR MOVED ABOVE THIS
|
||||
// old stuff
|
||||
// -------------
|
||||
|
||||
// Private
|
||||
//
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
@import "ui-variables";
|
||||
@import "ui-mixins";
|
||||
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
|
@ -100,7 +103,7 @@ atom-workspace {
|
|||
padding-right:3px;
|
||||
}
|
||||
&.flexbox-handle-bottom {
|
||||
bottom: 0px;
|
||||
bottom: 0;
|
||||
padding-right:2px;
|
||||
}
|
||||
}
|
||||
|
|