# # QuickSchedule # # A fairly complex package which allows you to select calendar availabilities # to email. Whoever receives your email with your availabilities can click on # your availabilities to schedule an appointment with you. {ComponentRegistry, DatabaseStore, DraftStore, QuotedHTMLTransformer, ExtensionRegistry, Event} = require 'nylas-exports' url = require('url') qs = require("querystring") CalendarButton = require './calendar-button' AvailabilityComposerExtension = require './availability-composer-extension' protocol = require('remote').require('protocol') # A simple class for building HTML in code class HtmlNode constructor: (name) -> @name = name @attrs = {} @styles = {} @children = [] attr: (k,v,isJson=false) -> @attrs[k] = if isJson then btoa(v) else v return @ style: (k,v) -> @styles[k] = v return @ append: (node) -> @children.push(node) return node appendNode: (name) -> node = new HtmlNode(name) return @append(node) appendText: (text) -> @append(text) return @ toString: -> attrs = ("#{k}=\"#{v}\"" for k,v of @attrs).join(" ") styles = ("#{k}: #{v};" for k,v of @styles).join(" ") if @children?.length > 0 children = (if n instanceof HtmlNode then n.toString() else n for n in @children).join("\n") return "<#{@name} #{attrs} style=\"#{styles}\">\n#{children}\n#{@name}>" else return "<#{@name} #{attrs} style=\"#{styles}\" />" module.exports = ### Package Methods ### # Activate is called when the package is loaded. If your package previously # saved state using `serialize` it is provided. # activate: (@state) -> # Using `ComponentRegistry.register`, we insert an instance of # `CalendarButton` into the `'Composer:ActionButton'` section of the # application, to sit along with the other React components already inside # `'Composer:ActionButton'`. ComponentRegistry.register CalendarButton, role: 'Composer:ActionButton' # You can add your own extensions to the N1 Composer view and the original # Composer by invoking `ExtensionRegistry.Composer.register` with a subclass of # `ComposerExtension`. ExtensionRegistry.Composer.register AvailabilityComposerExtension # Register a protocol that allows the calendar window to pass data back to the plugin # with web requests if NylasEnv.isMainWindow() # First unregister the protocol, in case it has already been registered with a callback that's no # longer valid (e.g. if the main window has reloaded). If the protocol is not registered, this line # does nothing. protocol.unregisterProtocol('quick-schedule') # Now register the new protocol protocol.registerStringProtocol 'quick-schedule', (request, callback) => {host:event,query:rawQuery} = url.parse(request.url) stringArgs = qs.parse(rawQuery) data = {} for own k,v of stringArgs data[k] = JSON.parse(v) response = @_onCalendarEvent(event,data,callback) # Serialize is called when your package is about to be unmounted. # You can return a state object that will be passed back to your package # when it is re-activated. # serialize: -> # This **optional** method is called when the window is shutting down, # or when your package is being updated or disabled. If your package is # watching any files, holding external resources, providing commands or # subscribing to events, release them here. # deactivate: -> ComponentRegistry.unregister CalendarButton ExtensionRegistry.Composer.unregister AvailabilityComposerExtension if NylasEnv.isMainWindow() protocol.unregisterProtocol('quick-schedule') ### Internal Methods ### _onCalendarEvent: (event,data,callback) -> switch event when "get_events" {start,end,id:eventId} = data DatabaseStore.findAll(Event).where([ Event.attributes.start.lessThan(end), Event.attributes.end.greaterThan(start), ]).then (events) => callback(JSON.stringify(events)) when "available_times" {draftClientId,eventData,events} = data.data @_addBlockToDraft(events,draftClientId,eventData) # Grabs the current draft text, appends the quick-schedule HTML block to it, and saves _addBlockToDraft: (events,draftClientId,eventData) -> # Obtain the session for the current draft. DraftStore.sessionForClientId(draftClientId).then (session) => draftHtml = session.draft().body # Remove any quoted text at the end of the message text = QuotedHTMLTransformer.removeQuotedHTML(draftHtml) # Check for an N1 signature and split that off sigIndex = text.indexOf('