-
Notifications
You must be signed in to change notification settings - Fork 7
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
Import data from a google spreadsheet #903
Conversation
devduarte
commented
May 12, 2021
- Add a new input field to enter a google spreadsheet link.
- Add a new endpoint to retrieve the spreadsheet link
- Create a csv file importing the spreadsheet data
- Continue the csv import process as always using the created csv file in the previous step
…orm to paste the spreadsheet url
app/views/import_wizards/index.haml
Outdated
%form#upload_form{action: upload_csv_collection_import_wizard_path(collection), method: :post, enctype: 'multipart/form-data', style: 'display: inline-block'} | ||
%input{type: :hidden, name: 'authenticity_token', value: form_authenticity_token} | ||
%div | ||
.icon.fexport.black Upload a CSV file to update multiple sites | ||
%input#upload{type: :file, name: :file, style: 'visibility:hidden; width:1px; height: 1px'} | ||
%form#upload_form_spreadsheet{action: import_csv_from_google_spreadsheet_collection_import_wizard_path(collection), method: :post, enctype: 'multipart/form-data', style: 'display: inline-block'} | ||
%input{type: :hidden, name: 'authenticity_token', value: form_authenticity_token} | ||
.icon.syes_no.black{style: 'cursor: pointer;'} or add a spreadsheet url | ||
%input{type: 'text', id: :spreadSheetLink, name: 'spreadSheetLink', placeholder: 'Enter url', style: 'width: 300px;'} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was not very sure where to put these css properties since there are not a lot stylesheets files. I know inline styles are not a good practice but since they were being used across several places in the application, I kind of followed the same rule.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to be ResourceMap's way - it's OK 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather add some documentation and error handling before merging. The feature looks nice, though :)
end | ||
|
||
def from_google_spreadsheet(spread_sheet_link) | ||
filename = "#{current_user.id}_#{collection.id}.csv" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this work if the same user imports a spreadsheet into a collection after having imported a previous one? What potential conflicts could arise then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The file's content gets overwritten with the spreadsheet content that the user inputs. Filename does not change, but content does. We could use the spreadsheet id as the filename, but then we will have stored a csv file for every single spreadsheet users want to import.
With the current code we will have one spreadsheet per user that used the feature as the worst case scenario.
app/models/spreadsheet_service.rb
Outdated
class SpreadsheetService | ||
def self.get_data(spreadsheet_id) | ||
service = Google::Apis::SheetsV4::SheetsService.new | ||
service.key = ENV['GOOGLE_SHEET_API_KEY'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add some documentation regarding this API Key (how to get it, what configurations may be needed).
app/models/spreadsheet_service.rb
Outdated
|
||
def self.get_range(spreadsheet_id) | ||
service = Google::Apis::SheetsV4::SheetsService.new | ||
service.key = ENV['GOOGLE_SHEET_API_KEY'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's take a look at how other configurations are used on the app.
Rails has the Settings
global object that allows users to configure the app via different mechanisms (the different environments' yml files, environment variables, etc). Instead of only supporting environment variables, let's use that. And we avoid having direct ENV
access from the business code - which is harder to track.
begin | ||
response = service.get_spreadsheet_values(spreadsheet_id, range) | ||
rescue Exception => e | ||
raise ActionController::BadRequest.new(), e.message() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess we need to add some error handling regarding the Spreadsheet import - catch the exception, log it, show some error to the user asking to contact the site admin?
app/views/import_wizards/index.haml
Outdated
$(".fexport").on("click", function(){ | ||
document.getElementById('upload').click(); | ||
}); | ||
$(".syes_no").on("click", function(){ | ||
$('#upload_form_spreadsheet').submit(); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add IDs to these clickable elements? .fexport
is referring to a CSS class, which may be applied to multiple elements - but we probably don't want other .fexport
s to trigger this very same action.
app/views/import_wizards/index.haml
Outdated
%form#upload_form{action: upload_csv_collection_import_wizard_path(collection), method: :post, enctype: 'multipart/form-data', style: 'display: inline-block'} | ||
%input{type: :hidden, name: 'authenticity_token', value: form_authenticity_token} | ||
%div | ||
.icon.fexport.black Upload a CSV file to update multiple sites | ||
%input#upload{type: :file, name: :file, style: 'visibility:hidden; width:1px; height: 1px'} | ||
%form#upload_form_spreadsheet{action: import_csv_from_google_spreadsheet_collection_import_wizard_path(collection), method: :post, enctype: 'multipart/form-data', style: 'display: inline-block'} | ||
%input{type: :hidden, name: 'authenticity_token', value: form_authenticity_token} | ||
.icon.syes_no.black{style: 'cursor: pointer;'} or add a spreadsheet url | ||
%input{type: 'text', id: :spreadSheetLink, name: 'spreadSheetLink', placeholder: 'Enter url', style: 'width: 300px;'} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to be ResourceMap's way - it's OK 👍
…n error message to the user.
…n those ids and not on icon classes
The code had the wrong identation, so the upload controls were only shown for empty collections. This commit moves the code to where it belongs, so only the Download section changes depending on having sites or not.
So we can easily configure it on Rancher/Docker
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job!
app/views/import_wizards/index.haml
Outdated
%div | ||
%form#upload_form{action: upload_csv_collection_import_wizard_path(collection), method: :post, enctype: 'multipart/form-data', style: 'display: inline-block'} | ||
%input{type: :hidden, name: 'authenticity_token', value: form_authenticity_token} | ||
%div | ||
#upload_icon_csv.icon.fexport.black Upload a CSV file to update multiple sites | ||
%input#upload{type: :file, name: :file, style: 'visibility:hidden; width:1px; height: 1px'} | ||
%form#upload_form_spreadsheet{action: import_csv_from_google_spreadsheet_collection_import_wizard_path(collection), method: :post, enctype: 'multipart/form-data', style: 'display: inline-block'} | ||
%input{type: :hidden, name: 'authenticity_token', value: form_authenticity_token} | ||
#upload_icon_spreadsheet.icon.syes_no.black{style: 'cursor: pointer;'} or add a spreadsheet url | ||
%input{type: 'text', id: :spreadSheetLink, name: 'spreadSheetLink', placeholder: 'Enter url', style: 'width: 300px;'} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MEGA fail 😂.
The %div
(with the %form
s and all) got moved inside the -else
clause of the -if
. So if you already have sites in your collection, you won't see the Upload section anymore.
I hadn't notice it in my previous review, either.
So we should basically unindent this whole block. I've just fixed that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahaha, nice catch! Thanks for the fix! :D
They are breaking, probably due to the changes in #903 being incompatible with old versions of Firefox - the engine is not able to find the upload <input> control.
They are breaking, probably due to the changes in #903 being incompatible with old versions of Firefox - the engine is not able to find the upload <input> control.