diff --git a/internal_packages/github/assets/github@2x.png b/examples/N1-Github/assets/github@2x.png similarity index 100% rename from internal_packages/github/assets/github@2x.png rename to examples/N1-Github/assets/github@2x.png diff --git a/internal_packages/github/keymaps/github.cson b/examples/N1-Github/keymaps/github.cson similarity index 100% rename from internal_packages/github/keymaps/github.cson rename to examples/N1-Github/keymaps/github.cson diff --git a/internal_packages/github/lib/github-store.coffee b/examples/N1-Github/lib/github-store.coffee similarity index 100% rename from internal_packages/github/lib/github-store.coffee rename to examples/N1-Github/lib/github-store.coffee diff --git a/internal_packages/github/lib/main.cjsx b/examples/N1-Github/lib/main.cjsx similarity index 100% rename from internal_packages/github/lib/main.cjsx rename to examples/N1-Github/lib/main.cjsx diff --git a/internal_packages/github/lib/view-on-github-button.cjsx b/examples/N1-Github/lib/view-on-github-button.cjsx similarity index 100% rename from internal_packages/github/lib/view-on-github-button.cjsx rename to examples/N1-Github/lib/view-on-github-button.cjsx diff --git a/internal_packages/github/package.json b/examples/N1-Github/package.json similarity index 100% rename from internal_packages/github/package.json rename to examples/N1-Github/package.json diff --git a/internal_packages/github/stylesheets/github.less b/examples/N1-Github/stylesheets/github.less similarity index 100% rename from internal_packages/github/stylesheets/github.less rename to examples/N1-Github/stylesheets/github.less diff --git a/internal_packages/calendar-bar/.gitignore b/internal_packages/calendar-bar/.gitignore deleted file mode 100755 index 3c3629e64..000000000 --- a/internal_packages/calendar-bar/.gitignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/internal_packages/calendar-bar/README.md b/internal_packages/calendar-bar/README.md deleted file mode 100755 index a781a1fc6..000000000 --- a/internal_packages/calendar-bar/README.md +++ /dev/null @@ -1 +0,0 @@ -# React version of thread list diff --git a/internal_packages/calendar-bar/lib/calendar-bar-event-store.coffee b/internal_packages/calendar-bar/lib/calendar-bar-event-store.coffee deleted file mode 100644 index d23a334ff..000000000 --- a/internal_packages/calendar-bar/lib/calendar-bar-event-store.coffee +++ /dev/null @@ -1,72 +0,0 @@ -Reflux = require 'reflux' -_ = require 'underscore' -{DatabaseStore, - AccountStore, - Actions, - Event, - Calendar, - NylasAPI} = require 'nylas-exports' -moment = require 'moment' - -CalendarBarEventStore = Reflux.createStore - init: -> - @_setStoreDefaults() - @_registerListeners() - @_populate() - @trigger(@) - - ########### PUBLIC ##################################################### - - events: -> - @_events - - range: -> - @_range - - ########### PRIVATE #################################################### - - _setStoreDefaults: -> - @_events = [] - - _registerListeners: -> - @listenTo DatabaseStore, @_onDataChanged - @listenTo AccountStore, @_onAccountChanged - - _populate: -> - @_range = - start: moment({hour: 0, milliseconds: -1}).valueOf() / 1000.0 - end: moment({hour: 24, milliseconds: 1}).valueOf() / 1000.0 - - account = AccountStore.current() - return unless account - - DatabaseStore.findAll(Event, accountId: account.id).where([ - Event.attributes.end.greaterThan(@_range.start), - Event.attributes.start.lessThan(@_range.end) - ]).order(Event.attributes.start.ascending()).then (events) => - @_events = events - @trigger(@) - - _refetchFromAPI: -> - account = AccountStore.current() - return unless account - - # Trigger a request to the API - oneDayAgo = Math.round(moment({hour: 0, milliseconds: -1}).valueOf() / 1000.0) - DatabaseStore.findAll(Calendar, accountId: account.id).then (calendars) -> - calendars.forEach (calendar) -> - NylasAPI.getCollection(account.id, 'events', {calendar_id: calendar.id, ends_after: oneDayAgo}) - - # Inbound Events - - _onAccountChanged: -> - @_refetchFromAPI() - @_populate() - - _onDataChanged: (change) -> - if change.objectClass == Calendar.name - @_refetchFromAPI() - if change.objectClass == Event.name - @_populate() - -module.exports = CalendarBarEventStore diff --git a/internal_packages/calendar-bar/lib/calendar-bar-item.cjsx b/internal_packages/calendar-bar/lib/calendar-bar-item.cjsx deleted file mode 100644 index b0a2d79f9..000000000 --- a/internal_packages/calendar-bar/lib/calendar-bar-item.cjsx +++ /dev/null @@ -1,37 +0,0 @@ -React = require 'react' -{Actions} = require("nylas-exports") -moment = require 'moment' - -# TODO: This file is out of date! -return - -class CalendarBarItem extends React.Component - render: => - style = - left: @props.item.xPercent - top: @props.item.yPercent - width: @props.item.wPercent - height: @props.item.hPercent - zIndex: @props.item.z -
- {@props.item.event.title} - {@_time()} -
- - _time: => - w = @props.item.event.when - if w.start_time - return moment.unix(w.start_time).format('h:mm a') - else if w.time - return moment.unix(w.time).format('h:mm a') - else if w.start_date - return moment.unix(w.start_date).format('MMMM Do') - else - return "" - - _onClick: (event) => - event.preventDefault() - Actions.focusMailView(@props.tag) - - -module.exports = CalendarBarItem diff --git a/internal_packages/calendar-bar/lib/calendar-bar.cjsx b/internal_packages/calendar-bar/lib/calendar-bar.cjsx deleted file mode 100644 index d9e4d9d05..000000000 --- a/internal_packages/calendar-bar/lib/calendar-bar.cjsx +++ /dev/null @@ -1,127 +0,0 @@ -React = require 'react' -{Actions} = require("nylas-exports") -CalendarBarItem = require("./calendar-bar-item") -CalendarBarEventStore = require ("./calendar-bar-event-store") - -class CalendarBarRow - constructor: (initialItem = null) -> - @items = [] - @last = 0 - if initialItem - @last = initialItem.event.end - @items.push(initialItem) - - canHoldItem: (item) => - item.event.start > @last - - addItem: (item) => - @last = item.event.end - @items.push(item) - -class CalendarBarMarker extends React.Component - @displayName: "CalendarBarMarker" - - render: => - classname = "marker" - classname += " now" if @props.marker.now -
- -class CalendarBar extends React.Component - @displayName: "CalendarBar" - - constructor: (@props) -> - @state = @_getStateFromStores() - - componentDidMount: => - @unsubscribe = CalendarBarEventStore.listen @_onStoreChange - - # It's important that every React class explicitly stops listening to - # atom events before it unmounts. Thank you event-kit - # This can be fixed via a Reflux mixin - componentWillUnmount: => - @unsubscribe() if @unsubscribe - - render: => - markers = @_getMarkers().map (marker) -> - - - items = @_getItemsForEvents(@state.events) - items = items.map (item) -> - - -
- {markers} - {items} -
- - _onStoreChange: => - @setState @_getStateFromStores() - - _getStateFromStores: => - events: CalendarBarEventStore.events() - range: CalendarBarEventStore.range() - - _getMarkers: => - range = @state.range - now = (new Date).getTime()/1000 - range.start - markers = [] - for hour in [0..24] - time = 60*60*hour - markers.push - xPercent: (time * 100) / (range.end - range.start) + "%" - markers.push - now: true - xPercent: (now * 100) / (range.end - range.start) + "%" - markers - - _getItemsForEvents: (events) => - # Create an array of items with additional metadata needed for our view. - # We compute the X and width of elements using their durations as a fraction - # of the displayed range - range = @state.range - items = events.map (event) -> - { - event: event, - z: event.start - range.start - xPercent: (event.start - range.start) * 100 / (range.end - range.start) + "%", - wPercent: (event.end - event.start) * 100 / (range.end - range.start) + "%" - } - - # Compute the number of rows we need by assigning events to rows. This works by - # creating virtual "row" objects which hold a series of non-overlapping events and - # have a "last" timestamp. For each item, we iterate through the rows: - # - # - If the event fits in more than one row, we delete all but one of the rows. - # This ensures that if we have two overlapping events, the next event that - # does not overlap goes back to taking all of the available height. (Rows no - # longer necessary) - # - # - If the event does not fit in any rows, we create a new row, and tell all of - # the items in existing rows that they're now sharing space with a new row. - - rows = [new CalendarBarRow] - for item in items - for x in [rows.length-1..0] by -1 - if rows[x].canHoldItem(item) - rows.splice(item.rowIndex, 1) unless item.rowIndex is undefined - rows[x].addItem(item) - item.rowIndex = x - - if item.rowIndex is undefined - rows.push(new CalendarBarRow(item)) - item.rowIndex = rows.length - 1 - for row in rows - for item in row.items - item.rowCount += 1 - - item.rowCount = rows.length - - # Now that each item knows what row it's in and how many rows are being displayed - # alongside it, we can assign fractional positions to them. - for item in items - item.yPercent = (item.rowIndex / item.rowCount) * 100 + "%" - item.hPercent = (100.0 / item.rowCount) + "%" - - items - -module.exports = CalendarBar diff --git a/internal_packages/calendar-bar/lib/main.cjsx b/internal_packages/calendar-bar/lib/main.cjsx deleted file mode 100644 index 7cb68abd4..000000000 --- a/internal_packages/calendar-bar/lib/main.cjsx +++ /dev/null @@ -1,9 +0,0 @@ -React = require "react" - -module.exports = - activate: (@state) -> - # Package turned off for now - - deactivate: -> - - serialize: -> @state diff --git a/internal_packages/calendar-bar/package.json b/internal_packages/calendar-bar/package.json deleted file mode 100755 index 8331a6df7..000000000 --- a/internal_packages/calendar-bar/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "calendar-bar", - "version": "0.1.0", - "main": "./lib/main", - "description": "Footer bar that shows your daily availability", - "license": "Proprietary", - "private": true, - "engines": { - "atom": "*" - }, - "dependencies": { - } -} diff --git a/internal_packages/calendar-bar/stylesheets/calendar-bar.less b/internal_packages/calendar-bar/stylesheets/calendar-bar.less deleted file mode 100644 index d6b33c894..000000000 --- a/internal_packages/calendar-bar/stylesheets/calendar-bar.less +++ /dev/null @@ -1,53 +0,0 @@ -@import "ui-variables"; -@import "ui-mixins"; - - -#calendar-bar { - height: 45px; - overflow: hidden; - order: 50; - box-shadow: @standard-shadow-up; - z-index:2; // allows shadow over other elements - position: relative; - - .marker { - position: absolute; - border-left:1px solid @border-color-subtle; - width:1px; - height:100%; - top:0; - z-index:0; - &.now { - width:4px; - z-index:1000; - border-right:1px solid white; - border-left:1px solid white; - background-color:@background-color-success; - } - } - - .event { - position: absolute; - border:2px solid white; - background-color: @background-color-accent; - padding:3px; - - span { - float:left; - font-weight: normal; - text-overflow: ellipsis; - white-space: nowrap; - overflow:hidden; - color: @text-color-inverse; - width:100%; - } - - span.title { - font-size:12px; - } - span.time { - font-size:10px; - opacity: 0.5; - } - } -} diff --git a/internal_packages/file-list/.gitignore b/internal_packages/file-list/.gitignore deleted file mode 100755 index 3c3629e64..000000000 --- a/internal_packages/file-list/.gitignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/internal_packages/file-list/lib/file-frame-store.coffee b/internal_packages/file-list/lib/file-frame-store.coffee deleted file mode 100644 index c120c40bf..000000000 --- a/internal_packages/file-list/lib/file-frame-store.coffee +++ /dev/null @@ -1,55 +0,0 @@ -Reflux = require 'reflux' -_ = require 'underscore' -fs = require 'fs' - -{WorkspaceStore, - FocusedContentStore, - FileDownloadStore, - Actions} = require 'nylas-exports' - -module.exports = -FileFrameStore = Reflux.createStore - init: -> - @_resetInstanceVars() - @_afterViewUpdate = [] - - @listenTo FocusedContentStore, @_onFocusedContentChange - @listenTo FileDownloadStore, @_onFileDownloadChange - - file: -> - @_file - - ready: -> - @_ready - - download: -> - @_download - - _resetInstanceVars: -> - @_file = null - @_download = null - @_ready = false - - _update: -> - - _onFileDownloadChange: -> - @_download = FileDownloadStore.downloadDataForFile(@_file.id) if @_file - if @_file and @_ready is false and not @_download - @_ready = true - @trigger() - - _onFocusedContentChange: (change) -> - return unless change.impactsCollection('file') - - @_file = FocusedContentStore.focused('file') - if @_file - filepath = FileDownloadStore.pathForFile(@_file) - fs.exists filepath, (exists) => - Actions.fetchFile(@_file) if not exists - @_download = FileDownloadStore.downloadDataForFile(@_file.id) - @_ready = not @_download - @trigger() - else - @_ready = false - @_download = null - @trigger() diff --git a/internal_packages/file-list/lib/file-frame.cjsx b/internal_packages/file-list/lib/file-frame.cjsx deleted file mode 100644 index e5e4d733f..000000000 --- a/internal_packages/file-list/lib/file-frame.cjsx +++ /dev/null @@ -1,39 +0,0 @@ -React = require 'react' -_ = require "underscore" -{Utils, FileDownloadStore, Actions} = require 'nylas-exports' -{Spinner, EventedIFrame} = require 'nylas-component-kit' -FileFrameStore = require './file-frame-store' - -class FileFrame extends React.Component - @displayName: 'FileFrame' - - render: => - src = if @state.ready then @state.filepath else '' - if @state.file -
- - -
- else -
- - constructor: (@props) -> - @state = @getStateFromStores() - - componentDidMount: => - @_unsubscribers = [] - @_unsubscribers.push FileFrameStore.listen @_onChange - - componentWillUnmount: => - unsubscribe() for unsubscribe in @_unsubscribers - - getStateFromStores: => - file: FileFrameStore.file() - filepath: FileDownloadStore.pathForFile(FileFrameStore.file()) - ready: FileFrameStore.ready() - - _onChange: => - @setState(@getStateFromStores()) - - -module.exports = FileFrame diff --git a/internal_packages/file-list/lib/file-list-store.coffee b/internal_packages/file-list/lib/file-list-store.coffee deleted file mode 100644 index 2c227f0b8..000000000 --- a/internal_packages/file-list/lib/file-list-store.coffee +++ /dev/null @@ -1,20 +0,0 @@ -Reflux = require 'reflux' -_ = require 'underscore' -{File, - DatabaseStore, - DatabaseView} = require 'nylas-exports' - -module.exports = -FileListStore = Reflux.createStore - init: -> - @listenTo DatabaseStore, @_onDataChanged - - @_view = new DatabaseView(File, matchers: [File.attributes.filename.not('')]) - @listenTo @_view, => @trigger({}) - - view: -> - @_view - - _onDataChanged: (change) -> - return unless change.objectClass is File.name - @_view.invalidate({shallow: true, changed: change.objects}) diff --git a/internal_packages/file-list/lib/file-list.cjsx b/internal_packages/file-list/lib/file-list.cjsx deleted file mode 100644 index 21d8261bb..000000000 --- a/internal_packages/file-list/lib/file-list.cjsx +++ /dev/null @@ -1,51 +0,0 @@ -_ = require 'underscore' -React = require 'react' -{ListTabular, MultiselectList} = require 'nylas-component-kit' -{Actions, - DatabaseStore, - ComponentRegistry} = require 'nylas-exports' -FileListStore = require './file-list-store' - -class FileList extends React.Component - @displayName: 'FileList' - - @containerRequired: false - - componentWillMount: => - prettySize = (size) -> - units = ['GB', 'MB', 'KB', 'bytes'] - while size > 1024 - size /= 1024 - units.pop() - size = "#{(Math.ceil(size * 10) / 10)}" - pretty = units.pop() - "#{size} #{pretty}" - - c1 = new ListTabular.Column - name: "Name" - flex: 1 - resolver: (file) => -
{file.displayName()}
- - c2 = new ListTabular.Column - name: "Size" - width: '100px' - resolver: (file) => -
{prettySize(file.size)}
- - @columns = [c1, c2] - - render: => - {} } - className="file-list" - collection="file" /> - - _onDoubleClick: (item) => - - -module.exports = FileList diff --git a/internal_packages/file-list/lib/file-selection-bar.cjsx b/internal_packages/file-list/lib/file-selection-bar.cjsx deleted file mode 100644 index 5ed7fa2dc..000000000 --- a/internal_packages/file-list/lib/file-selection-bar.cjsx +++ /dev/null @@ -1,14 +0,0 @@ -React = require "react/addons" -FileListStore = require './file-list-store' -{MultiselectActionBar} = require 'nylas-component-kit' - -class FileSelectionBar extends React.Component - @displayName: 'FileSelectionBar' - - render: => - - - -module.exports = FileSelectionBar diff --git a/internal_packages/file-list/lib/main.cjsx b/internal_packages/file-list/lib/main.cjsx deleted file mode 100644 index 725d5aa8b..000000000 --- a/internal_packages/file-list/lib/main.cjsx +++ /dev/null @@ -1,30 +0,0 @@ -# FileFrame = require "./file-frame" -# FileList = require './file-list' -# FileSelectionBar = require './file-selection-bar' -# {ComponentRegistry, -# WorkspaceStore} = require 'nylas-exports' - -module.exports = - - activate: (@state={}) -> - # WorkspaceStore.defineSheet 'Files', {root: true, supportedModes: ['list'], name: 'Files'}, - # list: ['RootSidebar', 'FileList'] - # - # WorkspaceStore.defineSheet 'File', {supportedModes: ['list']}, - # list: ['File'] - # - # ComponentRegistry.register FileList, - # location: WorkspaceStore.Location.FileList - # - # ComponentRegistry.register FileSelectionBar, - # location: WorkspaceStore.Location.FileList.Toolbar - # - # ComponentRegistry.register FileFrame, - # location: WorkspaceStore.Location.File - - deactivate: -> - # ComponentRegistry.unregister(FileList) - # ComponentRegistry.unregister(FileSelectionBar) - # ComponentRegistry.unregister(FileFrame) - # WorkspaceStore.undefineSheet('Files') - # WorkspaceStore.undefineSheet('File') diff --git a/internal_packages/file-list/package.json b/internal_packages/file-list/package.json deleted file mode 100755 index 70061034b..000000000 --- a/internal_packages/file-list/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "file-list", - "version": "0.1.0", - "main": "./lib/main", - "description": "View files", - "license": "Proprietary", - "private": true, - "engines": { - "atom": "*" - }, - "dependencies": { - } -} diff --git a/internal_packages/file-list/stylesheets/file-list.less b/internal_packages/file-list/stylesheets/file-list.less deleted file mode 100644 index 27e2bf69f..000000000 --- a/internal_packages/file-list/stylesheets/file-list.less +++ /dev/null @@ -1,15 +0,0 @@ -@import "ui-variables"; -@import "ui-mixins"; - -@message-max-width: 800px; - -.file-frame-container { - width:100%; - height:100%; - - iframe { - width:100%; - height:100%; - border:0; - } -} \ No newline at end of file diff --git a/internal_packages/message-templates/lib/draft-extension.coffee b/internal_packages/message-templates/lib/draft-extension.coffee deleted file mode 100644 index 7a045f176..000000000 --- a/internal_packages/message-templates/lib/draft-extension.coffee +++ /dev/null @@ -1,116 +0,0 @@ -{DraftStoreExtension} = require 'nylas-exports' - -class TemplatesDraftStoreExtension extends DraftStoreExtension - - @warningsForSending: (draft) -> - warnings = [] - if draft.body.search(/]*empty[^>]*>/i) > 0 - warnings.push("with an empty template area") - warnings - - @finalizeSessionBeforeSending: (session) -> - body = session.draft().body - clean = body.replace(/<\/?code[^>]*>/g, '') - if body != clean - session.changes.add(body: clean) - - @onMouseUp: (editableNode, range, event) -> - parent = range.startContainer?.parentNode - parentCodeNode = null - - while parent and parent isnt editableNode - if parent.classList?.contains('var') and parent.tagName is 'CODE' - parentCodeNode = parent - break - parent = parent.parentNode - - isSinglePoint = range.startContainer is range.endContainer and range.startOffset is range.endOffset - - if isSinglePoint and parentCodeNode - range.selectNode(parentCodeNode) - selection = document.getSelection() - selection.removeAllRanges() - selection.addRange(range) - - @onFocusPrevious: (editableNode, range, event) -> - @onFocusShift(editableNode, range, event, -1) - - @onFocusNext: (editableNode, range, event) -> - @onFocusShift(editableNode, range, event, 1) - - @onFocusShift: (editableNode, range, event, delta) -> - return unless range - - # Try to find the node that the selection range is - # currently intersecting with (inside, or around) - parentCodeNode = null - nodes = editableNode.querySelectorAll('code.var') - for node in nodes - if range.intersectsNode(node) - parentCodeNode = node - - - if parentCodeNode - if range.startOffset is range.endOffset and parentCodeNode.classList.contains('empty') - # If the current node is empty and it's a single insertion point, - # select the current node rather than advancing to the next node - selectNode = parentCodeNode - else - # advance to the next code node - matches = editableNode.querySelectorAll('code.var') - matchIndex = -1 - for match, idx in matches - if match is parentCodeNode - matchIndex = idx - break - if matchIndex != -1 and matchIndex + delta >= 0 and matchIndex + delta < matches.length - selectNode = matches[matchIndex+delta] - - else - # We're not currently intersecting a code node. Find the one we want - # to move to by scanning for the next one in the DOM. Traversing the - # structure of the email would be hard, so instead we look for the next - # one that is *visually* to the left or beneath the current one, vice - # versa for going back (delta -1 case) - rangeRect = range.getClientRects()[0] - if rangeRect - if delta is 1 # next - for node in nodes - nodeRect = node.getBoundingClientRect() - continue if nodeRect.top < rangeRect.top - if nodeRect.top > rangeRect.top or nodeRect.left > rangeRect.left - selectNode = node - break - else if delta is -1 # previous - for node in nodes by -1 - nodeRect = node.getBoundingClientRect() - continue if nodeRect.top > rangeRect.top - if nodeRect.top < rangeRect.top or nodeRect.left < rangeRect.left - selectNode = node - break - - if selectNode - range.selectNode(selectNode) - selection = document.getSelection() - selection.removeAllRanges() - selection.addRange(range) - event.preventDefault() - event.stopPropagation() - - @onInput: (editableNode, event) -> - selection = document.getSelection() - - isWithinNode = (node) -> - test = selection.baseNode - while test isnt editableNode - return true if test is node - test = test.parentNode - return false - - codeTags = editableNode.querySelectorAll('code.var.empty') - for codeTag in codeTags - if selection.containsNode(codeTag) or isWithinNode(codeTag) - codeTag.classList.remove('empty') - - -module.exports = TemplatesDraftStoreExtension diff --git a/internal_packages/message-templates/lib/main.cjsx b/internal_packages/message-templates/lib/main.cjsx deleted file mode 100644 index 5fbd82422..000000000 --- a/internal_packages/message-templates/lib/main.cjsx +++ /dev/null @@ -1,25 +0,0 @@ -React = require "react" -{ComponentRegistry, DraftStore} = require 'nylas-exports' -TemplatePicker = require './template-picker' -TemplateStatusBar = require './template-status-bar' -Extension = require './draft-extension' -_ = require 'underscore' - -module.exports = - item: null # The DOM item the main React component renders into - - activate: (@state={}) -> - ComponentRegistry.register TemplatePicker, - role: 'Composer:ActionButton' - - ComponentRegistry.register TemplateStatusBar, - role: 'Composer:Footer' - - DraftStore.registerExtension(Extension) - - deactivate: -> - ComponentRegistry.unregister(TemplatePicker) - ComponentRegistry.unregister(TemplateStatusBar) - DraftStore.unregisterExtension(Extension) - - serialize: -> @state diff --git a/internal_packages/message-templates/lib/template-picker.cjsx b/internal_packages/message-templates/lib/template-picker.cjsx deleted file mode 100644 index 57659e10b..000000000 --- a/internal_packages/message-templates/lib/template-picker.cjsx +++ /dev/null @@ -1,87 +0,0 @@ -_ = require 'underscore' -React = require 'react' -TemplateStore = require './template-store' -{Actions, Message, DatabaseStore} = require 'nylas-exports' -{Popover, Menu, RetinaImg} = require 'nylas-component-kit' - -class TemplatePicker extends React.Component - @displayName: 'TemplatePicker' - - @containerStyles: - order:2 - - constructor: (@props) -> - @state = - searchValue: "" - templates: TemplateStore.items() - - componentDidMount: => - @unsubscribe = TemplateStore.listen @_onStoreChange - - componentWillUnmount: => - @unsubscribe() if @unsubscribe - - render: => - button = - - headerComponents = [ - - ] - - footerComponents = [ -
Save Draft as Template...
-
Open Templates Folder...
- ] - - - item.id } - itemContent={ (item) -> item.name } - onSelect={@_onChooseTemplate} - /> - - - - _filteredTemplates: (search) => - search ?= @state.searchValue - items = TemplateStore.items() - - return items unless search.length - - _.filter items, (t) -> - t.name.toLowerCase().indexOf(search.toLowerCase()) == 0 - - _onStoreChange: => - @setState - templates: @_filteredTemplates() - - _onSearchValueChange: => - newSearch = event.target.value - @setState - searchValue: newSearch - templates: @_filteredTemplates(newSearch) - - _onChooseTemplate: (template) => - Actions.insertTemplateId({templateId:template.id, draftClientId: @props.draftClientId}) - @refs.popover.close() - - _onManageTemplates: => - Actions.showTemplates() - - _onNewTemplate: => - Actions.createTemplate({draftClientId: @props.draftClientId}) - - -module.exports = TemplatePicker diff --git a/internal_packages/message-templates/lib/template-status-bar.cjsx b/internal_packages/message-templates/lib/template-status-bar.cjsx deleted file mode 100644 index e903ca546..000000000 --- a/internal_packages/message-templates/lib/template-status-bar.cjsx +++ /dev/null @@ -1,47 +0,0 @@ -_ = require 'underscore' -React = require 'react' -{Actions, Message, DraftStore} = require 'nylas-exports' - -class TemplateStatusBar extends React.Component - @displayName: 'TemplateStatusBar' - - @containerStyles: - textAlign:'center' - width:530 - margin:'auto' - - @propTypes: - draftClientId: React.PropTypes.string - - constructor: (@props) -> - @state = draft: null - - componentDidMount: => - DraftStore.sessionForClientId(@props.draftClientId).then (_proxy) => - return if @_unmounted - return unless _proxy.draftClientId is @props.draftClientId - @_proxy = _proxy - @unsubscribe = @_proxy.listen(@_onDraftChange, @) - @_onDraftChange() - - componentWillUnmount: => - @_unmounted = true - @unsubscribe() if @unsubscribe - - render: => - if @_draftUsesTemplate() -
- Press "tab" to quickly fill in the blanks - highlighting will not be visible to recipients. -
- else -
- - _onDraftChange: => - @setState(draft: @_proxy.draft()) - - _draftUsesTemplate: => - return unless @state.draft - @state.draft.body.search(/]*class="var[^>]*>/i) > 0 - - -module.exports = TemplateStatusBar diff --git a/internal_packages/message-templates/lib/template-store.coffee b/internal_packages/message-templates/lib/template-store.coffee deleted file mode 100644 index 7431784f3..000000000 --- a/internal_packages/message-templates/lib/template-store.coffee +++ /dev/null @@ -1,104 +0,0 @@ -Reflux = require 'reflux' -_ = require 'underscore' -{DatabaseStore, DraftStore, Actions, Message} = require 'nylas-exports' -shell = require 'shell' -path = require 'path' -fs = require 'fs-plus' - -TemplateStore = Reflux.createStore - init: -> - @_setStoreDefaults() - @_registerListeners() - - @_templatesDir = path.join(atom.getConfigDirPath(), 'templates') - - # I know this is a bit of pain but don't do anything that - # could possibly slow down app launch - fs.exists @_templatesDir, (exists) => - if exists - @_populate() - fs.watch @_templatesDir, => @_populate() - else - fs.mkdir @_templatesDir, => - fs.watch @_templatesDir, => @_populate() - - - ########### PUBLIC ##################################################### - - items: -> - @_items - - templatesDirectory: -> - @_templatesDir - - - ########### PRIVATE #################################################### - - _setStoreDefaults: -> - @_items = [] - - _registerListeners: -> - @listenTo Actions.insertTemplateId, @_onInsertTemplateId - @listenTo Actions.createTemplate, @_onCreateTemplate - @listenTo Actions.showTemplates, @_onShowTemplates - - _populate: -> - fs.readdir @_templatesDir, (err, filenames) => - @_items = [] - for filename in filenames - continue if filename[0] is '.' - displayname = path.basename(filename, path.extname(filename)) - @_items.push - id: filename, - name: displayname, - path: path.join(@_templatesDir, filename) - @trigger(@) - - _onCreateTemplate: ({draftClientId, name, contents} = {}) -> - if draftClientId - DraftStore.sessionForClientId(draftClientId).then (session) => - draft = session.draft() - name ?= draft.subject - contents ?= draft.body - if not name or name.length is 0 - return @_displayError("Give your draft a subject to name your template.") - if not contents or contents.length is 0 - return @_displayError("To create a template you need to fill the body of the current draft.") - @_writeTemplate(name, contents) - - else - if not name or name.length is 0 - return @_displayError("You must provide a name for your template.") - if not contents or contents.length is 0 - return @_displayError("You must provide contents for your template.") - @_writeTemplate(name, contents) - - _onShowTemplates: -> - shell.showItemInFolder(@_items[0]?.path || @_templatesDir) - - _displayError: (message) -> - dialog = require('remote').require('dialog') - dialog.showErrorBox('Template Creation Error', message) - - _writeTemplate: (name, contents) -> - filename = "#{name}.html" - templatePath = path.join(@_templatesDir, filename) - fs.writeFile templatePath, contents, (err) => - @_displayError(err) if err - shell.showItemInFolder(templatePath) - @_items.push - id: filename, - name: name, - path: templatePath - @trigger(@) - - _onInsertTemplateId: ({templateId, draftClientId} = {}) -> - template = _.find @_items, (item) -> item.id is templateId - return unless template - - fs.readFile template.path, (err, data) -> - body = data.toString() - DraftStore.sessionForClientId(draftClientId).then (session) -> - session.changes.add(body: body) - -module.exports = TemplateStore diff --git a/internal_packages/message-templates/package.json b/internal_packages/message-templates/package.json deleted file mode 100755 index 526f8ad38..000000000 --- a/internal_packages/message-templates/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "message-templates", - "version": "0.1.0", - "main": "./lib/main", - "description": "Template features galore!", - "license": "Proprietary", - "private": true, - "engines": { - "atom": "*" - }, - "dependencies": { - }, - "windowTypes": { - "default": true, - "composer": true - } -} diff --git a/internal_packages/message-templates/spec/template-store-spec.coffee b/internal_packages/message-templates/spec/template-store-spec.coffee deleted file mode 100644 index 7b02a25bc..000000000 --- a/internal_packages/message-templates/spec/template-store-spec.coffee +++ /dev/null @@ -1,139 +0,0 @@ -{Message, Actions, DatabaseStore, DraftStore} = require 'nylas-exports' -TemplateStore = require '../lib/template-store' -fs = require 'fs-plus' -shell = require 'shell' - -stubTemplatesDir = TemplateStore.templatesDirectory() - -stubTemplateFiles = { - 'template1.html': '

bla1

', - 'template2.html': '

bla2

' -} - -stubTemplates = [ - {id: 'template1.html', name: 'template1', path: "#{stubTemplatesDir}/template1.html"}, - {id: 'template2.html', name: 'template2', path: "#{stubTemplatesDir}/template2.html"}, -] - -describe "TemplateStore", -> - beforeEach -> - spyOn(fs, 'mkdir') - spyOn(shell, 'showItemInFolder').andCallFake -> - spyOn(fs, 'writeFile').andCallFake (path, contents, callback) -> - callback(null) - spyOn(fs, 'readFile').andCallFake (path, callback) -> - filename = path.split('/').pop() - callback(null, stubTemplateFiles[filename]) - - it "should create the templates folder if it does not exist", -> - spyOn(fs, 'exists').andCallFake (path, callback) -> callback(false) - TemplateStore.init() - expect(fs.mkdir).toHaveBeenCalled() - - it "should expose templates in the templates directory", -> - spyOn(fs, 'exists').andCallFake (path, callback) -> callback(true) - spyOn(fs, 'readdir').andCallFake (path, callback) -> callback(null, Object.keys(stubTemplateFiles)) - TemplateStore.init() - expect(TemplateStore.items()).toEqual(stubTemplates) - - it "should watch the templates directory and reflect changes", -> - watchCallback = null - watchFired = false - - spyOn(fs, 'exists').andCallFake (path, callback) -> callback(true) - spyOn(fs, 'watch').andCallFake (path, callback) -> watchCallback = callback - spyOn(fs, 'readdir').andCallFake (path, callback) -> - if watchFired - callback(null, Object.keys(stubTemplateFiles)) - else - callback(null, []) - - TemplateStore.init() - expect(TemplateStore.items()).toEqual([]) - - watchFired = true - watchCallback() - expect(TemplateStore.items()).toEqual(stubTemplates) - - describe "insertTemplateId", -> - it "should insert the template with the given id into the draft with the given id", -> - - add = jasmine.createSpy('add') - spyOn(DraftStore, 'sessionForClientId').andCallFake -> - Promise.resolve(changes: {add}) - - runs -> - TemplateStore._onInsertTemplateId - templateId: 'template1.html', - draftClientId: 'localid-draft' - waitsFor -> - add.calls.length > 0 - runs -> - expect(add).toHaveBeenCalledWith - body: stubTemplateFiles['template1.html'] - - describe "onCreateTemplate", -> - beforeEach -> - TemplateStore.init() - spyOn(DraftStore, 'sessionForClientId').andCallFake (draftClientId) -> - if draftClientId is 'localid-nosubject' - d = new Message(subject: '', body: '

Body

') - else - d = new Message(subject: 'Subject', body: '

Body

') - session = - draft: -> d - Promise.resolve(session) - - it "should create a template with the given name and contents", -> - TemplateStore._onCreateTemplate({name: '123', contents: 'bla'}) - item = TemplateStore.items()?[0] - expect(item.id).toBe "123.html" - expect(item.name).toBe "123" - expect(item.path.split("/").pop()).toBe "123.html" - - it "should display an error if no name is provided", -> - spyOn(TemplateStore, '_displayError') - TemplateStore._onCreateTemplate({contents: 'bla'}) - expect(TemplateStore._displayError).toHaveBeenCalled() - - it "should display an error if no content is provided", -> - spyOn(TemplateStore, '_displayError') - TemplateStore._onCreateTemplate({name: 'bla'}) - expect(TemplateStore._displayError).toHaveBeenCalled() - - it "should save the template file to the templates folder", -> - TemplateStore._onCreateTemplate({name: '123', contents: 'bla'}) - path = "#{stubTemplatesDir}/123.html" - expect(fs.writeFile).toHaveBeenCalled() - expect(fs.writeFile.mostRecentCall.args[0]).toEqual(path) - expect(fs.writeFile.mostRecentCall.args[1]).toEqual('bla') - - it "should open the template so you can see it", -> - TemplateStore._onCreateTemplate({name: '123', contents: 'bla'}) - path = "#{stubTemplatesDir}/123.html" - expect(shell.showItemInFolder).toHaveBeenCalled() - - describe "when given a draft id", -> - it "should create a template from the name and contents of the given draft", -> - spyOn(TemplateStore, 'trigger') - spyOn(TemplateStore, '_populate') - runs -> - TemplateStore._onCreateTemplate({draftClientId: 'localid-b'}) - waitsFor -> - TemplateStore.trigger.callCount > 0 - runs -> - expect(TemplateStore.items().length).toEqual(1) - - it "should display an error if the draft has no subject", -> - spyOn(TemplateStore, '_displayError') - runs -> - TemplateStore._onCreateTemplate({draftClientId: 'localid-nosubject'}) - waitsFor -> - TemplateStore._displayError.callCount > 0 - runs -> - expect(TemplateStore._displayError).toHaveBeenCalled() - - describe "onShowTemplates", -> - it "should open the templates folder in the Finder", -> - TemplateStore._onShowTemplates() - expect(shell.showItemInFolder).toHaveBeenCalled() diff --git a/internal_packages/message-templates/stylesheets/message-templates.less b/internal_packages/message-templates/stylesheets/message-templates.less deleted file mode 100755 index 4a4091bcf..000000000 --- a/internal_packages/message-templates/stylesheets/message-templates.less +++ /dev/null @@ -1,38 +0,0 @@ -@import "ui-variables"; -@import "ui-mixins"; - -@code-bg-color: #fcf4db; - -.template-picker { - .menu { - .content-container { - height:150px; - overflow-y:scroll; - } - } -} - -.template-status-bar { - background-color: @code-bg-color; - color: darken(@code-bg-color, 70%); - border: 1.5px solid darken(@code-bg-color, 10%); - border-radius: @border-radius-small; - padding-top: @padding-small-vertical @padding-small-horizontal @padding-small-vertical @padding-small-horizontal; - font-size: @font-size-small; -} - -.compose-body #contenteditable { - code.var { - font: inherit; - padding:0; - padding-left:2px; - padding-right:2px; - border-bottom: 1.5px solid darken(@code-bg-color, 10%); - background-color: fade(@code-bg-color, 10%); - &.empty { - color:darken(@code-bg-color, 70%); - border-bottom: 1px solid darken(@code-bg-color, 14%); - background-color: @code-bg-color; - } - } -} diff --git a/internal_packages/today/assets/HurmeGeometricSans4Thin.otf b/internal_packages/today/assets/HurmeGeometricSans4Thin.otf deleted file mode 100755 index cdf86a416..000000000 Binary files a/internal_packages/today/assets/HurmeGeometricSans4Thin.otf and /dev/null differ diff --git a/internal_packages/today/assets/background.png b/internal_packages/today/assets/background.png deleted file mode 100644 index d4b0c4b82..000000000 Binary files a/internal_packages/today/assets/background.png and /dev/null differ diff --git a/internal_packages/today/lib/main.cjsx b/internal_packages/today/lib/main.cjsx deleted file mode 100644 index c65796a6d..000000000 --- a/internal_packages/today/lib/main.cjsx +++ /dev/null @@ -1,17 +0,0 @@ -TodayView = require "./today-view" -TodayIcon = require "./today-icon" -{ComponentRegistry, - WorkspaceStore} = require 'nylas-exports' - -module.exports = - - activate: (@state={}) -> - # WorkspaceStore.defineSheet 'Today', {root: true, supportedModes: ['list'], name: 'Today', icon: 'today.png'}, - # list: ['RootSidebar', 'Today'] - # - # ComponentRegistry.register TodayView, - # location: WorkspaceStore.Location.Today - - deactivate: -> - # ComponentRegistry.unregister(TodayView) - # WorkspaceStore.undefineSheet('Today') diff --git a/internal_packages/today/lib/today-icon.cjsx b/internal_packages/today/lib/today-icon.cjsx deleted file mode 100644 index 0b3735e4c..000000000 --- a/internal_packages/today/lib/today-icon.cjsx +++ /dev/null @@ -1,32 +0,0 @@ -React = require 'react' -_ = require "underscore" -moment = require 'moment' -classNames = require 'classnames' - -class TodayIcon extends React.Component - @displayName: 'TodayIcon' - - constructor: (@props) -> - @state = - moment: moment() - - componentDidMount: => - @_setTimeState() - - componentWillUnmount: => - clearInterval(@_timer) - - render: => - classes = classNames - 'today-icon': true - 'selected': @props.selected - -
{@state.moment.format('D')}
- - _setTimeState: => - timeTillNextSecond = (60 - (new Date).getSeconds()) * 1000 - @_timer = setTimeout(@_setTimeState, timeTillNextSecond) - @setState(moment: moment()) - - -module.exports = TodayIcon diff --git a/internal_packages/today/lib/today-view.cjsx b/internal_packages/today/lib/today-view.cjsx deleted file mode 100644 index 7c5127be4..000000000 --- a/internal_packages/today/lib/today-view.cjsx +++ /dev/null @@ -1,83 +0,0 @@ -React = require 'react' -_ = require "underscore" -{Utils, Actions} = require 'nylas-exports' -{Spinner, EventedIFrame} = require 'nylas-component-kit' -moment = require 'moment' - -class TodayViewDateTime extends React.Component - @displayName: 'TodayViewDateTime' - - constructor: (@props) -> - @state = - moment: moment() - - componentDidMount: => - @_setTimeState() - - componentWillUnmount: => - clearInterval(@_timer) - - render: => -
-
{@state.moment.format('h:mm')}
-
{@state.moment.format('dddd, MMM Do')}
-
- - _setTimeState: => - timeTillNextSecond = (60 - (new Date).getSeconds()) * 1000 - @_timer = setTimeout(@_setTimeState, timeTillNextSecond) - - @setState(moment: moment()) - - -class TodayViewBox extends React.Component - @displayName: 'TodayViewBox' - - @propTypes: - name: React.PropTypes.string.isRequired - - constructor: (@props) -> - - render: => -
-

{@props.name}

-
- -class TodayView extends React.Component - @displayName: 'TodayView' - - constructor: (@props) -> - @state = @_getStateFromStores() - - render: => -
-
- -
- - - - - - -
-
- Inbox -
-
-
- - componentDidMount: => - @_unsubscribers = [] - - componentWillUnmount: => - unsubscribe() for unsubscribe in @_unsubscribers - - _getStateFromStores: => - {} - - _onChange: => - @setState(@_getStateFromStores()) - - -module.exports = TodayView diff --git a/internal_packages/today/package.json b/internal_packages/today/package.json deleted file mode 100755 index 0a0593879..000000000 --- a/internal_packages/today/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "today", - "version": "0.1.0", - "main": "./lib/main", - "description": "Today View", - "license": "Proprietary", - "private": true, - "engines": { - "atom": "*" - }, - "dependencies": { - "moment": "^2.8" - } -} diff --git a/internal_packages/today/stylesheets/today-view.less b/internal_packages/today/stylesheets/today-view.less deleted file mode 100644 index de86465ca..000000000 --- a/internal_packages/today/stylesheets/today-view.less +++ /dev/null @@ -1,86 +0,0 @@ -@import "ui-variables"; -@import "ui-mixins"; - -@font-face { - font-family: 'Hurme'; - font-style: normal; - src: url(nylas://today/assets/HurmeGeometricSans4Thin.otf); -} - -.today-icon { - display:inline-block; - overflow:hidden; - width:16px; - height:16px; - color:@source-list-bg; - text-align:center; - font-weight:500; - font-size:11px; - line-height:16px; - position:relative; - top:5px; - background-color:@text-color-very-subtle; - - &.selected { - background-color:@accent-primary; - } -} -.today { - background:url(nylas://today/assets/background.png) top center no-repeat; - background-size:100%; - overflow-y:scroll; - position:absolute; - width:100%; - height:100%; - - .inner { - - } - - .to-the-inbox { - opacity:0.3; - position:absolute; - width:100%; - text-align:center; - bottom:10px; - font-weight:@font-weight-semi-bold; - } - .centered { - text-align:center; - opacity:0.6; - .time { - font-family: 'Hurme'; - margin-top:70px; - font-size:100px; - line-height:96px; - } - .date { - font-family:@font-family-sans-serif; - font-weight:@font-weight-normal; - font-size:22px; - } - } - .boxes { - display: flex; - flex-direction:row; - padding:15px; - position:absolute; - bottom:20px; - width:100%; - .box { - margin:15px; - border-radius: @border-radius-large; - background-color:white; - box-shadow: 0 1px 2px rgba(0,0,0,0.3); - flex:1; - height:40vh; - h2 { - margin-top:4px; - padding:12px; - border-bottom:1px solid #ccc; - font-size:15px; - font-weight:@font-weight-semi-bold; - } - } - } -}