Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for importing from Google Docs #75

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion scripts/gh-book/app.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ define [
'cs!collections/media-types'
'cs!gh-book/epub-container'
'cs!gh-book/xhtml-file'
'cs!gh-book/gdoc-xhtml-file'
'cs!gh-book/opf-file'
'cs!gh-book/toc-node'
'cs!gh-book/binary-file'
Expand All @@ -17,7 +18,7 @@ define [
'cs!gh-book/loading'
'cs!configs/github.coffee'
'less!gh-book/gh-book'
], ($, _, Backbone, Marionette, logger, session, allContent, mediaTypes, EpubContainer, XhtmlFile, OpfFile, TocNode, BinaryFile, WelcomeSignInView, remoteUpdater, LoadingView, config) ->
], ($, _, Backbone, Marionette, logger, session, allContent, mediaTypes, EpubContainer, XhtmlFile, GoogleDocXhtmlFile, OpfFile, TocNode, BinaryFile, WelcomeSignInView, remoteUpdater, LoadingView, config) ->

# Stop logging.
logger.stop()
Expand Down Expand Up @@ -94,6 +95,7 @@ define [
mediaTypes.add TocNode
mediaTypes.add BinaryFile, {mediaType:'image/png'}
mediaTypes.add BinaryFile, {mediaType:'image/jpeg'}
mediaTypes.add GoogleDocXhtmlFile, {mediaType:GoogleDocXhtmlFile::uniqueMediaType}

# set which media formats are allowed
# at the toplevel of the content
Expand Down
93 changes: 93 additions & 0 deletions scripts/gh-book/gdoc-xhtml-file.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
define [
'underscore'
'jquery'
'backbone'
'cs!models/content/module'
'cs!gh-book/xhtml-file'
'gh-book/googlejsapi'
], (_, $, Backbone, ModuleModel, XhtmlModel) ->

# Picker Reference: https://developers.google.com/picker/docs/reference

GDOC_TO_HTML_URL = 'http://testing.oerpub.org/gdoc2html' # eventually `http://remix.oerpub.org/gdoc2html`
gdocsURL = (id) -> "https://docs.google.com/document/d/#{id}/export?format=html&confirm=no_antivirus"

# Opens a new Modal Dialog allowing the user to pick a Google Doc to import
newPicker = () ->
promise = $.Deferred()

google.load 'picker', '1',
callback: () =>
# Create a new Doc Picker Modal popup and re-ify the promise when
# 1. a document is selected
# 2. the dialog is canceled/closed
builder = new google.picker.PickerBuilder()
builder.addView(google.picker.ViewId.DOCUMENTS)
builder.setCallback (data) ->
switch data.action
when google.picker.Action.PICKED then promise.resolve(data)
when google.picker.Action.CANCEL then promise.reject('USER_CANCELLED')
else
promise.progress(data)
picker = builder.build()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! I did the exact same thing locally, just forgot to commit it ; ) No wonder it worked for me.

picker.setVisible(true)
return picker

return promise.promise()

# Retreive the HTML of the 1st Google Doc selected in the Picker
getGoogleDocHtml = (data) ->
resourceId = data.docs[0].id
htmlUrl = gdocsURL(resourceId)
promise = $.get(htmlUrl)
return promise

# Clean up HTML retrieved from Google to be used in the Editor.
# Makes an AJAX call to a service that converts the HTML
transformGoogleDocHtml = (html) ->
promise = $.ajax
url: GDOC_TO_HTML_URL
type: 'POST'
dataType: 'json'
async: true
data:
html: html
textbook_html: 0
copy_images: 0

return promise

return class GoogleDocXhtmlModel extends XhtmlModel

title: 'Google Document Import'

# **NOTE:** The mediaType is inherited from XhtmlModel because a successful import will
# 'appear' as a XHTML document.
# This mediaType is used in the OPF manifest

# In order to add this type to the Add dropdown for a Book (OPF File)
# this model must have a unique mediaType (not `application/xhtml+xml`)
# This is used to register with `media-types` and is in the
# list of types `opf-file` accepts as a child (so it shows up in the filtered dropdown)
uniqueMediaType: 'application/vnd.org.cnx.gdoc-import'

# Saves the fetched and converted Document into this model for saving
_injectHtml: (html) -> @set('body', html) # html is '<body>...</body>'

# Pop up the Picker dialog when this Model is added to a book
_loadComplex: (fetchPromise) ->
# **NOTE:** `fetchPromise` is not used because this type can only be created as a new object
# (the fetchPromise is already resolved)

promise = newPicker() # 1. Open the picker dialog
.then (data) =>
return getGoogleDocHtml(data) # 2. Get the HTML from Google
.then (html) =>
return transformGoogleDocHtml(html) # 3. Send the HTML to the transform service
.then (json) =>
@_injectHtml(json.html) # 4. Inject the cleaned HTML into the Model

promise.fail =>
console.warn('BUG: Import failed (maybe the user canceled it) and there is no cleanup code')

return promise
3 changes: 2 additions & 1 deletion scripts/gh-book/gh-book.less
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
.x-media-type-icon('application/xhtml+xml'; "content/module"; #999; "\f0f6"); /* icon-file-alt */
.x-media-type-icon('application/oebps-package+xml'; "Book"; @toc-color; "\f02d"); /* icon-book */
.x-media-type-icon('application/vnd.org.cnx.section'; "book division"; #999; ""); /* icon-folder-open */
.x-media-type-icon('application/vnd.org.cnx.gdoc-import'; "Google Doc Import"; #999; "\f0d5"); /* icon-google-plus */

#login-advanced-wrapper {
margin-top: 1em;
Expand Down Expand Up @@ -173,4 +174,4 @@ nav#workspace-sidebar-toc{
content: "";
}

}
}
Loading