Merge branch 'feat-refactor-layout' of github.com:inboxapp/edgehill into feat-refactor-layout

Conflicts:
	src/flux/models/utils.coffee
This commit is contained in:
Evan Morikawa 2015-03-05 19:57:50 -08:00
commit 7e7f8e5eda
52 changed files with 395 additions and 576 deletions

View file

@ -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)

View file

@ -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')

View file

@ -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()

View file

@ -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']

View file

@ -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

View file

@ -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()

View file

@ -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

View file

@ -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: ->

View file

@ -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

View file

@ -41,7 +41,7 @@ NotificationStickyBar = React.createClass
@
render: ->
<div>
<div className="notifications-sticky">
{@_notificationComponents()}
</div>

View file

@ -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

View file

@ -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;
}
}
}

View file

@ -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)

View file

@ -2,8 +2,6 @@ Reflux = require 'reflux'
actions = [
"setEnvironment",
"createAccount",
"signIn",
"authErrorOccurred",
"startConnect",
"finishedConnect",

View file

@ -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()

View file

@ -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 {

View file

@ -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)

View file

@ -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;
}
}
}

View file

@ -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

View file

@ -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'

View file

@ -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'

View file

@ -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'

View file

@ -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'

View file

@ -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)'"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 361 KiB

After

Width:  |  Height:  |  Size: 361 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 KiB

After

Width:  |  Height:  |  Size: 19 KiB

BIN
resources/win/loading.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

View file

@ -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
}
];

View file

@ -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

View file

@ -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)

View file

@ -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'

View file

@ -13,6 +13,7 @@ Flexbox = React.createClass
render: ->
style = _.extend (@props.style || {}),
'flexDirection': @props.direction,
'position':'relative'
'display': 'flex'
'height':'100%'

View file

@ -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")

View file

@ -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)

View file

@ -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

View file

@ -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}"]

View file

@ -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

View file

@ -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) ->

View file

@ -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

View file

@ -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;
}
}

View file

@ -72,6 +72,9 @@
min-width: 5em;
background-color:transparent;
}
input:focus {
box-shadow: none;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 KiB

View file

@ -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;
}
}

View file

@ -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

View file

@ -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.

View file

@ -1,3 +1,6 @@
@import "ui-variables";
@import "ui-mixins";
//
// Typography
// --------------------------------------------------

View file

@ -1,3 +1,6 @@
@import "ui-variables";
@import "ui-mixins";
:focus {
outline: none;
}

View file

@ -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
//

View file

@ -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;
}
}