Add demo page

The demo page shows a form and an embedded google sheet side by side.
The form needs be be configured with a DEMO_FORM_ID environment variable.
This commit is contained in:
bumi 2020-04-12 00:59:43 +02:00
parent e68d4941f1
commit e46e68cc22
10 changed files with 163 additions and 18 deletions

View File

@ -1,2 +1,2 @@
//= link_tree ../images //= link_tree ../images
//= link_directory ../stylesheets .css //= link application.css

View File

@ -1,18 +1,3 @@
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
* vendor/assets/stylesheets directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
* files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope.
*
*= require_tree .
*= require_self
*/
@import "bulma/sass/utilities/initial-variables"; @import "bulma/sass/utilities/initial-variables";
@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,300;0,400;0,500;1,300;1,400&family=Lobster&family=Comfortaa:wght@400;500;600;700&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,300;0,400;0,500;1,300;1,400&family=Lobster&family=Comfortaa:wght@400;500;600;700&display=swap');
@import url('https://use.fontawesome.com/releases/v5.12.0/css/all.css'); @import url('https://use.fontawesome.com/releases/v5.12.0/css/all.css');
@ -40,6 +25,8 @@ $light: #fff;
@import 'bulma/bulma'; @import 'bulma/bulma';
@import './demo';
.is-font-logo { .is-font-logo {
font-family: 'Lobster', cursive; font-family: 'Lobster', cursive;
} }

View File

@ -0,0 +1,16 @@
section.demo {
height: 90vh;
min-height: 600px;
}
.demo-form {
border: 1px solid $grey-light;
padding: 1em;
height: 100%;
}
section.demo .container, section.demo .columns, section.demo .column {
height: 100%;
}
#demo-success {
text-align: center;
padding-top: 1em;
}

9
app/javascript/demo.js Normal file
View File

@ -0,0 +1,9 @@
document.addEventListener('DOMContentLoaded', function() {
var demoForm = document.getElementById('demo-form');
demoForm.addEventListener('tinyforms:submitted', function() {
var demoFields = document.getElementById('demo-fields');
var demoSucess = document.getElementById('demo-success');
demoFields.style.display = 'none';
demoSucess.style.display = 'block';
});
});

View File

@ -9,6 +9,8 @@ require("@rails/activestorage").start()
require("channels") require("channels")
require('burger_menu'); require('burger_menu');
require('tinyforms');
require('demo');
// Uncomment to copy all static images under ../images to the output folder and reference // Uncomment to copy all static images under ../images to the output folder and reference
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>) // them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)

View File

@ -0,0 +1,51 @@
window.tinyforms = {
init: function() {
var forms = document.querySelectorAll('form[data-tinyforms]');
forms.forEach(function(form) {
form.addEventListener('submit', tinyforms.onSubmit);
});
},
submitForm: function(form) {
return new Promise(function(resolve, reject) {
var action = form.getAttribute('action');
var formData = new FormData(form);
var xhr = new XMLHttpRequest();
xhr.open('POST', action, true);
xhr.setRequestHeader("Accept", "application/json");
xhr.onload = function () {
var response;
try {
response = JSON.parse(xhr.responseText);
} catch (e) {
response = xhr.responseText;
}
if (xhr.status >= 200 && xhr.status < 300) {
resolve(response);
} else {
reject(response);
}
};
xhr.onerror = function() {
reject(xhr.responseText)
};
xhr.send(formData);
});
},
onSubmit: function(e) {
e.preventDefault();
return tinyforms.submitForm(this)
.then((response) => {
this.dispatchEvent(new CustomEvent('tinyforms:submitted', {detail: { response: response }}));
})
.catch((response) => {
this.dispatchEvent(new CustomEvent('tinyforms:error', {detail: { response: response }}));
});
}
};
document.addEventListener('DOMContentLoaded', function() {
tinyforms.init();
});

View File

@ -13,11 +13,11 @@ class Form < ApplicationRecord
# TODO: use counter_cache option on association # TODO: use counter_cache option on association
def submissions_count def submissions_count
submissions.count @submissions_count ||= submissions.count
end end
def last_submission_date def last_submission_date
submissions.order(created_at: :desc).first&.created_at @last_submission_date ||= submissions.order(created_at: :desc).first&.created_at
end end
def deactivate!(reason = nil) def deactivate!(reason = nil)

View File

@ -0,0 +1,77 @@
<section class="section demo">
<div class="container content">
<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">
<h3>Demo</h3>
<p>
This short form is connected to the embedded document on the right. <br>
Submit the form and see the update of the document.
</p>
<div id="demo-success" style="display:none;">
<p class="is-size-4 has-text-success">
Thanks for your submission!
</p>
<p>See your entry in the spreadsheet?!</p>
<p>
<%= link_to "Get started now", signup_url, class: 'button' %>
</p>
</div>
<div id="demo-fields">
<div class="field">
<label class="label">What's your name?</label>
<div class="control">
<input class="input" type="text" name="Name" required="true" placeholder="Your name">
</div>
</div>
<div class="field">
<label class="label">Where are you from?</label>
<div class="control">
<div class="select">
<select name="Continent">
<option value="Africa">Africa</option>
<option value="Antartica">Antartica</option>
<option value="Asia">Asia</option>
<option value="Australia">Australia</option>
<option value="Europe">Europe</option>
<option value="North America">North America</option>
<option value="South America">South America</option>
<option value="Australia">Australia</option>
</select>
</div>
</div>
</div>
<div class="field">
<label class="label">Do you like Pizza with Pinapples?</label>
<div class="control">
<label class="radio">
<input type="radio" name="Pinapples Pizza?" required value="yes">
Yes
</label>
<label class="radio">
<input type="radio" name="Pinapples Pizza?" required value="no">
Hell, no!
</label>
</div>
</div>
<div class="field is-grouped">
<div class="control">
<button class="button is-link">Submit</button>
</div>
</div>
</div>
</form>
</div>
<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>
</div>
</div>
</div>
</section>

View File

@ -0,0 +1 @@
DEMO_FORM = Form.find_by(id: ENV['DEMO_FORM_ID'])

View File

@ -13,9 +13,11 @@ Rails.application.routes.draw do
# short URL for form page # short URL for form page
get '/s/:id/form' => 'forms#form', as: :form_submitter get '/s/:id/form' => 'forms#form', as: :form_submitter
get '/signup' => 'sessions#new', as: :signup # TODO: add proper signup page
get '/login' => 'sessions#new', as: :login get '/login' => 'sessions#new', as: :login
get '/logout' => 'sessions#destroy', as: :logout get '/logout' => 'sessions#destroy', as: :logout
get '/auth' => 'sessions#auth', as: :auth get '/auth' => 'sessions#auth', as: :auth
get '/demo' => 'home#demo', as: :demo
root 'home#index' root 'home#index'
end end