diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js index 5918193..1f88c80 100644 --- a/app/assets/config/manifest.js +++ b/app/assets/config/manifest.js @@ -1,2 +1,2 @@ //= link_tree ../images -//= link_directory ../stylesheets .css +//= link application.css diff --git a/app/assets/stylesheets/application.css.scss b/app/assets/stylesheets/application.css.scss index 0045e6f..8ec56d8 100644 --- a/app/assets/stylesheets/application.css.scss +++ b/app/assets/stylesheets/application.css.scss @@ -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 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'); @@ -40,6 +25,8 @@ $light: #fff; @import 'bulma/bulma'; +@import './demo'; + .is-font-logo { font-family: 'Lobster', cursive; } diff --git a/app/assets/stylesheets/demo.css.scss b/app/assets/stylesheets/demo.css.scss new file mode 100644 index 0000000..af052b0 --- /dev/null +++ b/app/assets/stylesheets/demo.css.scss @@ -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; +} diff --git a/app/javascript/demo.js b/app/javascript/demo.js new file mode 100644 index 0000000..77a530b --- /dev/null +++ b/app/javascript/demo.js @@ -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'; + }); +}); diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index 80561d9..fb7f3ef 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -9,6 +9,8 @@ require("@rails/activestorage").start() require("channels") require('burger_menu'); +require('tinyforms'); +require('demo'); // 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' %>) diff --git a/app/javascript/tinyforms.js b/app/javascript/tinyforms.js new file mode 100644 index 0000000..bcb446d --- /dev/null +++ b/app/javascript/tinyforms.js @@ -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(); +}); diff --git a/app/models/form.rb b/app/models/form.rb index a1a13ca..b4fa31b 100644 --- a/app/models/form.rb +++ b/app/models/form.rb @@ -13,11 +13,11 @@ class Form < ApplicationRecord # TODO: use counter_cache option on association def submissions_count - submissions.count + @submissions_count ||= submissions.count end def last_submission_date - submissions.order(created_at: :desc).first&.created_at + @last_submission_date ||= submissions.order(created_at: :desc).first&.created_at end def deactivate!(reason = nil) diff --git a/app/views/home/demo.html.erb b/app/views/home/demo.html.erb new file mode 100644 index 0000000..c1a2114 --- /dev/null +++ b/app/views/home/demo.html.erb @@ -0,0 +1,77 @@ +
+
+
+
+
+

Demo

+

+ This short form is connected to the embedded document on the right.
+ Submit the form and see the update of the document. +

+ + + +
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ +
+ +
+ + +
+
+ +
+
+ +
+
+
+
+
+ +
+ +
+
+
+
+ diff --git a/config/initializers/demo.rb b/config/initializers/demo.rb new file mode 100644 index 0000000..915b94c --- /dev/null +++ b/config/initializers/demo.rb @@ -0,0 +1 @@ +DEMO_FORM = Form.find_by(id: ENV['DEMO_FORM_ID']) diff --git a/config/routes.rb b/config/routes.rb index 5bc2fc6..b83fe22 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -13,9 +13,11 @@ Rails.application.routes.draw do # short URL for form page 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 '/logout' => 'sessions#destroy', as: :logout get '/auth' => 'sessions#auth', as: :auth + get '/demo' => 'home#demo', as: :demo root 'home#index' end