![]() |
Listing Generator form input |
![]() |
Listing generator output to HTML for ebay and JSON for saving to file |
The generator is built with javascript/jquery with handlebars template. Because it is completely client-side, it can load local JSON files but has no way of saving changes back as local files, hence every time a listing is generated or an edit is made, the JSON needs to be manually copied and saved to a file... quite a tedious and error-prone workflow.
To improve the process, I decided to integrate the Listing Generator to Google Drive since all our listing JSON files are stored on Google Drive already. This would allow files to be created, edited and saved all without leaving the browser. This integration took me about two days, overall went fairly well although a few things took some setting up & trial and error.
1. Enable Drive API and Drive SDK
Google's helpful Quick Start Guide for enabling Drive API also contains some handy sample code. I also enabled Drive SDK to allow the app to integrate with the Drive UI. I used the below authorisation scopes for create, edit , save files and be installed to user's Drive:https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.installAfter saving these Drive SDK settings in Google console, I could install the app to my Drive account and see my app integrated with the Drive UI.
2. Integration
I modified Google's sample code to integrate Listing Generator with Drive API:- authenticate with
gapi.auth.authorize
function connect($do,retryIfFail){ gapi.auth.authorize({ 'client_id': CLIENT_ID, 'scope': SCOPES, 'immediate': retryIfFail?true:false // try immediate mode first },function(authResult){ if (authResult && !authResult.error) { $do.resolve(authResult) // Access token has been successfully retrieved, requests can be sent to the API. } else { if(retryIfFail){ console.log('connection with immediate mode failed - retrying with non-immediate mode') connect($do,false); }else{ $do.reject('authentication failed'); } } }); return $do.promise(); }
The code to upload/update a file is slightly modified from Google's example. If fileId is given, it saves to an existing file, otherwise a new file is created. It's not very pretty code with all the boundary, delimiter and all that string concatenation.. but hey, whatever works.
An attempt to authorise with immediate mode is made first, and if it fails, it re-attempts with non-immediate mode. Immediate mode will not trigger a popup authorisation screen, but it only works for users that have already authorised the app before. (It took me awhile to figure out why my authorisation calls were failing when I was only using immediate mode) Non-immediate mode will force the user to reauthorise via popup window. If the user has authorised once via this process, immediate mode should work for the user from that point. (You may need to have immediate mode triggered on a mouse-click to prevent popup blockers) - parse URL parameter
state.action
to determine if opening existing file or creating a new one - if open:
- get file id from URL parameters
state.id
- load metadata with
gapi.client.request
- download file
metadata.downloadUrl
- when saving content to the same file, pass the loaded metadata and file id; use
PUT
method - if create:
- get folder id from URL parameters
state.folderId
- load folder metadata with
gapi.client.request
- when saving content to file, pass new metadata with
title
(new file name),mimetype
andfolderId
specified; use methodPOST
function updateFile(fileId, fileMetadata, fileData) { const boundary = '-------314159265358979323846'; const delimiter = "\r\n--" + boundary + "\r\n"; const close_delim = "\r\n--" + boundary + "--"; var $do = $.Deferred(); var contentType = 'application/json'; var base64Data = btoa(fileData); var multipartRequestBody = delimiter + 'Content-Type: application/json\r\n\r\n' + JSON.stringify(fileMetadata) + delimiter + 'Content-Type: ' + contentType + '\r\n' + 'Content-Transfer-Encoding: base64\r\n' + '\r\n' + base64Data + close_delim; var request = gapi.client.request({ 'path': '/upload/drive/v2/files' + (fileId?'/'+fileId:''), 'method': fileId?'PUT':'POST', 'params': {'uploadType': 'multipart', 'alt': 'json'}, 'headers': { 'Content-Type': 'multipart/mixed; boundary="' + boundary + '"' }, 'body': multipartRequestBody}); request.execute(function(file){ $do.resolve(file); }); return $do.promise(); }
![]() |
Google Drive UI integration - creating a new file with the app |
3. Publish app as a Google Chrome Web Store app
Even though my app is for internal use and would never be released publicly, I still had to publish it to the Chrome Web Store (albeit to a whitelist of users) for Drive UI integration to work for anyone else but me. This required registering an account (and paying $5), uploading a manifest.json file with the app information, an icon, screenshot & promo images. It's a fairly straightforward process, with a simpler setup and cheaper than Apple's process for getting an app up and running!Overall, I'm pretty happy with the end result. Generating/editing files with a much smoother workflow, and as a bonus: our files are now automatically version controlled in Google Drive!
Google Forms (or any tool from the Google Apps for Work ensemble for that matter) is just a tiny bit of what you actually need to facilitate workflows. It gives you a good sprint, but the majority of the workflow is still on you to manually handle.
ReplyDeleteCheck out please google drive workflow
No download slot machines work on various devices with out having a downloadable shopper since they are “no installation no registration” video games. Ame builders and casinos guarantee gamblers’ convenience by providing no signup for privateness causes – just follow 메리트카지노 in instant play. Caesars Slots is meant for those 21 and older for amusement purposes solely and doesn't supply ‘real money’ playing, or a chance to win actual money or actual prizes primarily based on game play. Playing or success on this game doesn't suggest future success at ‘real money’ playing. Caesars Slots doesn't require fee to access and play, however it additionally allows you to buy virtual items with actual money inside the game. You can disable in-app purchases in your device’s settings.
ReplyDelete