Merge branch 'master' into New-forms-page
This commit is contained in:
@@ -3,10 +3,13 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
if (!demoForm) {
|
||||
return;
|
||||
}
|
||||
demoForm.addEventListener('submit', function(e) {
|
||||
var submitButton = document.getElementById('demo-submit');
|
||||
submitButton.innerText = 'loading...';
|
||||
submitButton.disabled = 'true'
|
||||
});
|
||||
|
||||
demoForm.addEventListener('tinyforms:submitted', function(e) {
|
||||
console.log(e);
|
||||
console.log(e.detail);
|
||||
var name = document.getElementById('demo-submission-name');
|
||||
var demoFields = document.getElementById('demo-fields');
|
||||
var demoSucess = document.getElementById('demo-success');
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
require 'google/apis/sheets_v4'
|
||||
class Form < ApplicationRecord
|
||||
# Hash to translate an index to a A1 notation. e.g. 1 => 'B', 27 => 'AA'
|
||||
COLUMN_INDEX_TO_LETTER = Hash.new {|hash,key| hash[key] = hash[key - 1].next }.merge({0 => "A"})
|
||||
|
||||
belongs_to :user
|
||||
has_many :submissions, dependent: :destroy
|
||||
|
||||
before_validation :insert_defaults, on: :create
|
||||
after_create :create_spreadsheet
|
||||
|
||||
has_secure_token
|
||||
|
||||
encrypts :airtable_api_key
|
||||
encrypts :airtable_app_key
|
||||
|
||||
validates_presence_of :title
|
||||
validates_inclusion_of :backend_name, in: ['google_sheets', 'airtable']
|
||||
# Airtable validations
|
||||
validates_presence_of :airtable_api_key, if: :airtable?
|
||||
validates_presence_of :airtable_app_key, if: :airtable?
|
||||
validates_presence_of :airtable_table, if: :airtable?
|
||||
|
||||
# TODO: use counter_cache option on association
|
||||
def submissions_count
|
||||
@@ -28,63 +34,39 @@ class Form < ApplicationRecord
|
||||
self.user.active?
|
||||
end
|
||||
|
||||
def google_spreadsheet_url
|
||||
"https://docs.google.com/spreadsheets/d/#{google_spreadsheet_id}/edit" if google_spreadsheet_id.present?
|
||||
def airtable?
|
||||
backend_name == 'airtable'
|
||||
end
|
||||
|
||||
def google
|
||||
backend_name == 'google'
|
||||
end
|
||||
|
||||
def backend
|
||||
@backend ||= SpreadsheetBackends.const_get(backend_name.camelize).new(self)
|
||||
end
|
||||
|
||||
def spreadsheet_url
|
||||
backend.url
|
||||
end
|
||||
|
||||
def create_spreadsheet
|
||||
sheets = Google::Apis::SheetsV4::SheetsService.new
|
||||
sheets.authorization = user.google_authorization
|
||||
create_object = Google::Apis::SheetsV4::Spreadsheet.new(properties: { title: title})
|
||||
spreadsheet = sheets.create_spreadsheet(create_object)
|
||||
update(google_spreadsheet_id: spreadsheet.spreadsheet_id)
|
||||
backend.create
|
||||
end
|
||||
|
||||
def spreadsheet_service
|
||||
@spreadsheet_service ||= Google::Apis::SheetsV4::SheetsService.new.tap do |s|
|
||||
s.authorization = user.google_authorization
|
||||
end
|
||||
def append_to_spreadsheet(data)
|
||||
backend.append(data)
|
||||
end
|
||||
|
||||
def header_values
|
||||
@header_values ||= begin
|
||||
values = spreadsheet_service.get_spreadsheet_values(google_spreadsheet_id, 'A1:An').values
|
||||
# if there are no headers yet, return an empty array
|
||||
if values
|
||||
values[0].map(&:strip)
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def append(data)
|
||||
data = data.with_indifferent_access
|
||||
check_spreadsheed_headers!(data)
|
||||
|
||||
values = header_values.map { |key| data[key] }
|
||||
range = "A1:A#{COLUMN_INDEX_TO_LETTER[values.length]}1"
|
||||
value_range = Google::Apis::SheetsV4::ValueRange.new(values: [values], major_dimension: 'ROWS')
|
||||
|
||||
spreadsheet_service.append_spreadsheet_value(google_spreadsheet_id, range, value_range, value_input_option: 'USER_ENTERED')
|
||||
end
|
||||
|
||||
def check_spreadsheed_headers!(data)
|
||||
missing_headers = data.keys.map { |k| k.to_s.strip } - header_values
|
||||
append_missing_headers(missing_headers) unless missing_headers.empty?
|
||||
end
|
||||
|
||||
def append_missing_headers(missing_headers)
|
||||
start_column = COLUMN_INDEX_TO_LETTER[header_values.length]
|
||||
end_column = COLUMN_INDEX_TO_LETTER[header_values.length + missing_headers.length]
|
||||
range = "#{start_column}1:#{end_column}1"
|
||||
value_range = Google::Apis::SheetsV4::ValueRange.new(values: [missing_headers], major_dimension: 'ROWS')
|
||||
spreadsheet_service.update_spreadsheet_value(google_spreadsheet_id, range, value_range, value_input_option: 'USER_ENTERED')
|
||||
@header_values = nil # reset header values to refresh memoization on next access
|
||||
def spreadsheet_headers
|
||||
backend.headers
|
||||
end
|
||||
|
||||
def to_param
|
||||
token
|
||||
end
|
||||
|
||||
def insert_defaults
|
||||
self.backend_name ||= airtable_app_key.present? ? 'airtable' : 'google_sheets'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -44,7 +44,7 @@ class Submission < ApplicationRecord
|
||||
end
|
||||
|
||||
def append_to_spreadsheet
|
||||
result = form.append(data)
|
||||
update_column(:appended_at, Time.current) if result.updates.updated_rows > 0
|
||||
form.append_to_spreadsheet(data) &&
|
||||
update_column(:appended_at, Time.current)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</div>
|
||||
<div class="media-right has-text-right is-size-4">
|
||||
<figure class="image is-48x48 ">
|
||||
<%= link_to form.google_spreadsheet_url, {class: "has-text-success", target: "__blank"} do %>
|
||||
<%= link_to form.spreadsheet_url, {class: "has-text-success", target: "__blank"} do %>
|
||||
<i class="far fa-file-excel"></i>
|
||||
<% end %>
|
||||
</figure>
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
<%= submission_url(@form) %>
|
||||
</p>
|
||||
<p>
|
||||
<%= link_to 'Google spreadsheet', @form.google_spreadsheet_url %>
|
||||
<%= link_to 'Google spreadsheet', @form.spreadsheet_url %>
|
||||
</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<% @form.header_values.each do |value| %>
|
||||
<% @form.spreadsheet_headers.each do |value| %>
|
||||
<th><%= value %></th>
|
||||
<% end %>
|
||||
</tr>
|
||||
@@ -16,7 +16,7 @@
|
||||
<tbody>
|
||||
<% @submissions.each do |submission| %>
|
||||
<tr>
|
||||
<% @form.header_values.each do |column| %>
|
||||
<% @form.spreadsheet_headers.each do |column| %>
|
||||
<td><%= submission.data[column] %></td>
|
||||
<% end %>
|
||||
</tr>
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
<div class="columns">
|
||||
<div class="column is-one-third">
|
||||
<form class="form demo-form" id="demo-form" action="<%= submission_url(DEMO_FORM) %>" method="POST" enctype="multipart/form-data" data-tinyforms="true">
|
||||
<input type="hidden" name="ID" value="tinyforms_id">
|
||||
<h3>Demo</h3>
|
||||
<p>
|
||||
This short form is connected to the embedded <%= link_to 'document', DEMO_FORM.google_spreadsheet_url %> on the right. <br>
|
||||
This short form is connected to the embedded <%= link_to 'document', DEMO_FORM.spreadsheet_url %> on the right. <br>
|
||||
Submit the form and see the update of the document in realtime.
|
||||
</p>
|
||||
|
||||
@@ -15,7 +16,9 @@
|
||||
</p>
|
||||
<p>See your entry in the spreadsheet?!</p>
|
||||
<p>
|
||||
<%= link_to "Get started now", signup_url, class: 'button' %>
|
||||
<%= link_to "Create your form now!", signup_url, class: 'button' %>
|
||||
<br>
|
||||
or got <%= link_to 'further questions?', contact_url %>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -68,7 +71,7 @@
|
||||
|
||||
<div class="field is-grouped">
|
||||
<div class="control">
|
||||
<button class="button is-link">Submit</button>
|
||||
<button class="button is-link" id="demo-submit">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -77,7 +80,7 @@
|
||||
|
||||
<div class="column">
|
||||
<iframe id="demo-sheet" style="width:100%;height:100%;" src="https://docs.google.com/spreadsheets/d/<%= DEMO_FORM.google_spreadsheet_id %>/edit?usp=sharing&nocache=<%= Time.now.to_i %>#gid=0&range=<%= DEMO_FORM.submissions.count + 1 %>:<%= DEMO_FORM.submissions.count + 2 %>"></iframe>
|
||||
<p class="has-text-grey has-text-centered">Document not loading? <%= link_to 'Open it here', DEMO_FORM.google_spreadsheet_url %>.</p>
|
||||
<p class="has-text-grey has-text-centered">Document not loading? <%= link_to 'Open it here', DEMO_FORM.spreadsheet_url %>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
<div id="navbar-menu" class="navbar-menu">
|
||||
<div class="navbar-end">
|
||||
<a href="https://www.notion.so/Tinyforms-Help-Center-04f13b5908bc46cfb4283079a3cb1149" class="navbar-item">Help</a>
|
||||
<%= link_to 'Help', help_url, class: 'navbar-item' %>
|
||||
<div class="navbar-item">
|
||||
<% if !logged_in? -%>
|
||||
<%= link_to "Login", login_url, { :class => "button is-primary"} %>
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
<h1 class="title has-text-centered">
|
||||
Login
|
||||
</h1>
|
||||
<div class="button google">
|
||||
<%= link_to auth_at_provider_url(provider: 'google'), class: 'button google' do %>
|
||||
<svg viewBox="0 0 15 15" class="googleLogo" style="width: 14px; height: 14px; display: block; fill: currentcolor; flex-shrink: 0; backface-visibility: hidden; margin-right: 6px;"><path d="M 7.28571 6.4125L 7.28571 9L 11.3929 9C 11.2143 10.0875 10.1429 12.225 7.28571 12.225C 4.78571 12.225 2.78571 10.0875 2.78571 7.5C 2.78571 4.9125 4.82143 2.775 7.28571 2.775C 8.71429 2.775 9.64286 3.4125 10.1786 3.9375L 12.1429 1.9875C 10.8929 0.75 9.25 0 7.28571 0C 3.25 0 0 3.3375 0 7.5C 0 11.6625 3.25 15 7.28571 15C 11.5 15 14.25 11.9625 14.25 7.6875C 14.25 7.2 14.2143 6.825 14.1429 6.45L 7.28571 6.45L 7.28571 6.4125Z"></path></svg>
|
||||
Login with Google
|
||||
</div>
|
||||
<% end %>
|
||||
<hr>
|
||||
<p>
|
||||
As tinyforms builds on Google Sheets.<br>
|
||||
|
||||
Reference in New Issue
Block a user