diff --git a/Gemfile.lock b/Gemfile.lock index 4b18c531..bbaa7460 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1013,7 +1013,7 @@ GEM multi_json (~> 1) statsd-ruby (~> 1.1) bcrypt (3.1.16) - better_errors (2.7.1) + better_errors (2.8.3) coderay (>= 1.0.0) erubi (>= 1.0.0) rack (>= 0.9.0) @@ -1041,7 +1041,7 @@ GEM cocoon (1.2.15) codeclimate-test-reporter (1.0.9) simplecov (<= 0.13) - coderay (1.1.2) + coderay (1.1.3) coffee-rails (5.0.0) coffee-script (>= 2.2.0) railties (>= 5.2.0) diff --git a/app/assets/javascripts/_initialization.coffee b/app/assets/javascripts/_initialization.coffee deleted file mode 100644 index 83da2147..00000000 --- a/app/assets/javascripts/_initialization.coffee +++ /dev/null @@ -1,29 +0,0 @@ -## This file is prepended with an underscore to ensure it comes alphabetically-first -## when application.js includes all JS files in the directory with require_tree. -## Here be dragons. - -window.Notebook ||= {} -Notebook.init = -> - # Initialize MaterializeCSS stuff - M.AutoInit() - $('.sidenav').sidenav() - $('.quick-reference-sidenav').sidenav { - closeOnClick: true, - edge: 'right', - draggable: false - } - $('#recent-edits-sidenav').sidenav { - closeOnClick: true, - edge: 'right', - draggable: false - } - $('.slider').slider { height: 200, indicators: false } - $('.dropdown-trigger').dropdown { coverTrigger: false } - $('.tooltipped').tooltip { enterDelay: 50 } - $('.with-character-counter').characterCounter(); - $('.materialboxed').materialbox(); - -# We're using $ -> here for document readiness, but if we ever use Turbolinks we'd want: -# $(document).on "turbolinks:load", -> -$ -> - Notebook.init() \ No newline at end of file diff --git a/app/assets/javascripts/_initialization.js b/app/assets/javascripts/_initialization.js new file mode 100644 index 00000000..47bf8d7c --- /dev/null +++ b/app/assets/javascripts/_initialization.js @@ -0,0 +1,27 @@ +//# This file is prepended with an underscore to ensure it comes alphabetically-first +//# when application.js includes all JS files in the directory with require_tree. +//# Here be dragons. + +if (!window.Notebook) { window.Notebook = {}; } +Notebook.init = function() { + // Initialize MaterializeCSS stuff + M.AutoInit(); + $('.sidenav').sidenav(); + $('.quick-reference-sidenav').sidenav({ + closeOnClick: true, + edge: 'right', + draggable: false + }); + $('#recent-edits-sidenav').sidenav({ + closeOnClick: true, + edge: 'right', + draggable: false + }); + $('.slider').slider({ height: 200, indicators: false }); + $('.dropdown-trigger').dropdown({ coverTrigger: false }); + $('.tooltipped').tooltip({ enterDelay: 50 }); + $('.with-character-counter').characterCounter(); + $('.materialboxed').materialbox(); +}; + +$(() => Notebook.init()); diff --git a/app/assets/javascripts/collaboration.coffee b/app/assets/javascripts/collaboration.coffee deleted file mode 100644 index fcec61f4..00000000 --- a/app/assets/javascripts/collaboration.coffee +++ /dev/null @@ -1,8 +0,0 @@ -$ -> - # When a user clicks to remove a collaborator, we should remove them from the list of collaborators after the remote request finishes - $('a.js-remove-contributor[data-remote]').on 'ajax:success', (e, data, status, xhr) -> - - # Remove the image from the UI - $(this).closest('.collection-item').fadeOut().remove() # todo use animate.css for something more fun - - return \ No newline at end of file diff --git a/app/assets/javascripts/collaboration.js b/app/assets/javascripts/collaboration.js new file mode 100644 index 00000000..8183bf3e --- /dev/null +++ b/app/assets/javascripts/collaboration.js @@ -0,0 +1,5 @@ +// When a user clicks to remove a collaborator, we should remove them from the list of collaborators after the remote request finishes +$('a.js-remove-contributor[data-remote]').on('ajax:success', function(e, data, status, xhr) { + // Remove the image from the UI + $(this).closest('.collection-item').fadeOut().remove(); // todo use animate.css for something more fun +}); diff --git a/app/assets/javascripts/document_editor.coffee b/app/assets/javascripts/document_editor.coffee deleted file mode 100644 index 2c9ac9f0..00000000 --- a/app/assets/javascripts/document_editor.coffee +++ /dev/null @@ -1,117 +0,0 @@ -class Notebook.DocumentEditor - constructor: (@el) -> - return unless @el.length > 0 - - window.editor = new MediumEditor('#editor', - targetBlank: true - autoLink: false - buttonLabels: 'fontawesome' - toolbar: buttons: [ - 'bold' - 'italic' - 'underline' - 'strikethrough' - { - name: 'h1' - action: 'append-h2' - aria: 'header type 1' - tagNames: [ 'h2' ] - contentDefault: 'H1' - classList: [ 'custom-class-h1' ] - attrs: 'data-custom-attr': 'attr-value-h1' - } - { - name: 'h2' - action: 'append-h3' - aria: 'header type 2' - tagNames: [ 'h3' ] - contentDefault: 'H2' - classList: [ 'custom-class-h2' ] - attrs: 'data-custom-attr': 'attr-value-h2' - } - { - name: 'h3' - action: 'append-h4' - aria: 'header type 3' - tagNames: [ 'h4' ] - contentDefault: 'H3' - classList: [ 'custom-class-h3' ] - attrs: 'data-custom-attr': 'attr-value-h3' - } - 'justifyLeft' - 'justifyCenter' - 'justifyRight' - 'justifyFull' - 'orderedlist' - 'unorderedlist' - 'quote' - 'anchor' - 'removeFormat' - ] - anchorPreview: hideDelay: 0 - placeholder: text: 'Write as little or as much as you want!' - paste: forcePlainText: false) - - # Autosave - autosave_event = null - last_autosave = null - - autosave = -> - if autosave_event == null - - console.log 'Queueing autosave' - $('.js-autosave-icon').addClass 'grey-text' - $('.js-autosave-icon').removeClass 'black-text' - $('.js-autosave-icon').removeClass 'red-text' - $('.js-autosave-status').text 'Saving changes...' - - autosave_event = setTimeout((-> - console.log 'Autosaving...' - $('.js-autosave-status').text 'Saving...' - autosave_event = null - - # Do the autosave - last_autosave = $.ajax( - type: 'PATCH' - url: $('#editor').data('save-url'), - data: document: - title: $('#document_title').val() - body: $('#editor').html() - ) - - last_autosave.fail (jqXHR, textStatus) -> - $('.js-autosave-status').text 'There was a problem saving! We will try to save again, but please make sure you back up any changes.' - $('.js-autosave-status').addClass 'red-text' - $('.js-autosave-status').removeClass 'grey-text' - $('.js-autosave-status').removeClass 'black-text' - return - - # Done! - $('.js-autosave-icon').addClass 'black-text' - $('.js-autosave-icon').removeClass 'grey-text' - $('.js-autosave-icon').removeClass 'red-text' - $('.js-autosave-status').text 'Saved!' - - return - ), 2500) - - else - console.log 'Waiting for existing autosave' - - return - - editor.subscribe 'editableInput', autosave - $('#document_title').on 'change', autosave - $('#document_title').on 'keydown', autosave - $('.js-autosave-status').on 'click', autosave - - # Allow entering `tab` into the editor - $(document).delegate '#editor', 'keydown', (e) -> - keyCode = e.keyCode or e.which - if keyCode == 9 - e.preventDefault() - - return - -$ -> - new Notebook.DocumentEditor $("body.documents.edit") \ No newline at end of file diff --git a/app/assets/javascripts/document_editor.js b/app/assets/javascripts/document_editor.js new file mode 100644 index 00000000..8e4e2a2b --- /dev/null +++ b/app/assets/javascripts/document_editor.js @@ -0,0 +1,128 @@ +Notebook.DocumentEditor = class DocumentEditor { + constructor(el) { + this.el = el; + if (!(this.el.length > 0)) { return; } + + window.editor = new MediumEditor('#editor', { + targetBlank: true, + autoLink: false, + buttonLabels: 'fontawesome', + toolbar: { buttons: [ + 'bold', + 'italic', + 'underline', + 'strikethrough', + { + name: 'h1', + action: 'append-h2', + aria: 'header type 1', + tagNames: [ 'h2' ], + contentDefault: 'H1', + classList: [ 'custom-class-h1' ], + attrs: { 'data-custom-attr': 'attr-value-h1' + } + }, + { + name: 'h2', + action: 'append-h3', + aria: 'header type 2', + tagNames: [ 'h3' ], + contentDefault: 'H2', + classList: [ 'custom-class-h2' ], + attrs: { 'data-custom-attr': 'attr-value-h2' + } + }, + { + name: 'h3', + action: 'append-h4', + aria: 'header type 3', + tagNames: [ 'h4' ], + contentDefault: 'H3', + classList: [ 'custom-class-h3' ], + attrs: { 'data-custom-attr': 'attr-value-h3' + } + }, + 'justifyLeft', + 'justifyCenter', + 'justifyRight', + 'justifyFull', + 'orderedlist', + 'unorderedlist', + 'quote', + 'anchor', + 'removeFormat' + ] + }, + anchorPreview: { hideDelay: 0 + }, + placeholder: { text: 'Write as little or as much as you want!' + }, + paste: { forcePlainText: false + } + }); + + // Autosave + let autosave_event = null; + let last_autosave = null; + + const autosave = function() { + if (autosave_event === null) { + + console.log('Queueing autosave'); + $('.js-autosave-icon').addClass('grey-text'); + $('.js-autosave-icon').removeClass('black-text'); + $('.js-autosave-icon').removeClass('red-text'); + $('.js-autosave-status').text('Saving changes...'); + + autosave_event = setTimeout((function() { + console.log('Autosaving...'); + $('.js-autosave-status').text('Saving...'); + autosave_event = null; + + // Do the autosave + last_autosave = $.ajax({ + type: 'PATCH', + url: $('#editor').data('save-url'), + data: { document: { + title: $('#document_title').val(), + body: $('#editor').html() + } + } + }); + + last_autosave.fail(function(jqXHR, textStatus) { + $('.js-autosave-status').text('There was a problem saving! We will try to save again, but please make sure you back up any changes.'); + $('.js-autosave-status').addClass('red-text'); + $('.js-autosave-status').removeClass('grey-text'); + $('.js-autosave-status').removeClass('black-text'); + }); + + // Done! + $('.js-autosave-icon').addClass('black-text'); + $('.js-autosave-icon').removeClass('grey-text'); + $('.js-autosave-icon').removeClass('red-text'); + $('.js-autosave-status').text('Saved!'); + + }), 2500); + + } else { + console.log('Waiting for existing autosave'); + } + }; + + editor.subscribe('editableInput', autosave); + $('#document_title').on('change', autosave); + $('#document_title').on('keydown', autosave); + $('.js-autosave-status').on('click', autosave); + + // Allow entering `tab` into the editor + $(document).delegate('#editor', 'keydown', function(e) { + const keyCode = e.keyCode || e.which; + if (keyCode === 9) { + e.preventDefault(); + } + }); + } +}; + +$(() => new Notebook.DocumentEditor($("body.documents.edit"))); diff --git a/app/assets/javascripts/generators.js b/app/assets/javascripts/generators.js new file mode 100644 index 00000000..2fe9da4c --- /dev/null +++ b/app/assets/javascripts/generators.js @@ -0,0 +1,41 @@ +$(document).ready(function() { + + // Character name generator + $('.character_name_generator').click(function() { + const target = $(this).closest('.row').find('input[type=text]'); + $.ajax({ + dataType: 'text', + url: '/generate/character/name', + success(data) { + target.val(data); + } + }); + return 0; + }); + + // Character age generator + $('.character_age_generator').click(function() { + const target = $(this).closest('.row').find('input[type=text]'); + $.ajax({ + dataType: 'text', + url: '/generate/character/age', + success(data) { + target.val(data); + } + }); + return 0; + }); + + // Location name generator + $('.location_name_generator').click(function() { + const target = $(this).closest('.row').find('input[type=text]'); + $.ajax({ + dataType: 'text', + url: '/generate/location/name', + success(data) { + target.val(data); + } + }); + return 0; + }); +}); diff --git a/app/assets/javascripts/generators.js.coffee b/app/assets/javascripts/generators.js.coffee deleted file mode 100644 index 94b745f3..00000000 --- a/app/assets/javascripts/generators.js.coffee +++ /dev/null @@ -1,31 +0,0 @@ -$(document).ready -> - - # Character name generator - $('.character_name_generator').click -> - target = $(this).closest('.row').find('input[type=text]') - $.ajax - dataType: 'text' - url: '/generate/character/name' - success: (data) -> - target.val data - 0 - - # Character age generator - $('.character_age_generator').click -> - target = $(this).closest('.row').find('input[type=text]') - $.ajax - dataType: 'text' - url: '/generate/character/age' - success: (data) -> - target.val data - 0 - - # Location name generator - $('.location_name_generator').click -> - target = $(this).closest('.row').find('input[type=text]') - $.ajax - dataType: 'text' - url: '/generate/location/name' - success: (data) -> - target.val data - 0 diff --git a/app/assets/javascripts/help.coffee b/app/assets/javascripts/help.coffee deleted file mode 100644 index 24f83d18..00000000 --- a/app/assets/javascripts/help.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# Place all the behaviors and hooks related to the matching controller here. -# All this logic will automatically be available in application.js. -# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/image_uploads.coffee b/app/assets/javascripts/image_uploads.coffee deleted file mode 100644 index fb1db7e8..00000000 --- a/app/assets/javascripts/image_uploads.coffee +++ /dev/null @@ -1,6 +0,0 @@ -$ -> - # When a user clicks to delete an image, we should remove it from the list of images after the remote request finishes - $('a.js-remove-image[data-remote]').on 'ajax:success', (e, data, status, xhr) -> - # Remove the image from the UI - $(this).closest('.row').fadeOut().remove() # todo use animate.css for something more fun - return diff --git a/app/assets/javascripts/image_uploads.js b/app/assets/javascripts/image_uploads.js new file mode 100644 index 00000000..7fb373f0 --- /dev/null +++ b/app/assets/javascripts/image_uploads.js @@ -0,0 +1,5 @@ +// When a user clicks to delete an image, we should remove it from the list of images after the remote request finishes +$('a.js-remove-image[data-remote]').on('ajax:success', function(e, data, status, xhr) { + // Remove the image from the UI + $(this).closest('.row').fadeOut().remove(); // todo use animate.css for something more fun +}); diff --git a/app/assets/javascripts/pickers.js b/app/assets/javascripts/pickers.js new file mode 100644 index 00000000..d96602f1 --- /dev/null +++ b/app/assets/javascripts/pickers.js @@ -0,0 +1,4 @@ +$(document).ready(() => $('.dropdown-picker li a').click(function() { + const val = $(this).text(); + $(this).closest('.row').find('input[type=text]').val(val); +})); diff --git a/app/assets/javascripts/pickers.js.coffee b/app/assets/javascripts/pickers.js.coffee deleted file mode 100644 index 2268a4a5..00000000 --- a/app/assets/javascripts/pickers.js.coffee +++ /dev/null @@ -1,4 +0,0 @@ -$(document).ready -> - $('.dropdown-picker li a').click -> - val = $(this).text() - $(this).closest('.row').find('input[type=text]').val(val) diff --git a/app/assets/javascripts/stripe.coffee b/app/assets/javascripts/stripe.coffee deleted file mode 100644 index c321be5b..00000000 --- a/app/assets/javascripts/stripe.coffee +++ /dev/null @@ -1,36 +0,0 @@ -class Notebook.StripeHandler - constructor: (@el) -> - return unless @el.length > 0 - - $form = $('#payment-form') - stripeResponseHandler = (status, response) -> - $form = $('#payment-form') - if response.error - # Show the errors on the form: - $form.find('.payment-errors').text response.error.message - $form.find('.submit').prop 'disabled', false - - else - # Insert the created token ID into the form so it gets submitted to the server: - token = response.id - $form.append $('').val(token) - - # Submit the form: - $form.get(0).submit() - - return - - $form.submit (event) -> - # Disable the submit button to prevent repeated clicks: - $form.find('.submit').prop 'disabled', true - - # Request a token from Stripe: - Stripe.card.createToken $form, stripeResponseHandler - - # Prevent the form from being submitted: - false - - return - -$ -> - new Notebook.StripeHandler $("body.subscriptions.information") \ No newline at end of file diff --git a/app/assets/javascripts/stripe.js b/app/assets/javascripts/stripe.js new file mode 100644 index 00000000..ed844853 --- /dev/null +++ b/app/assets/javascripts/stripe.js @@ -0,0 +1,39 @@ +Notebook.StripeHandler = class StripeHandler { + constructor(el) { + this.el = el; + if (!(this.el.length > 0)) { return; } + + let $form = $('#payment-form'); + const stripeResponseHandler = function(status, response) { + $form = $('#payment-form'); + if (response.error) { + // Show the errors on the form: + $form.find('.payment-errors').text(response.error.message); + $form.find('.submit').prop('disabled', false); + + } else { + // Insert the created token ID into the form so it gets submitted to the server: + const token = response.id; + $form.append($('').val(token)); + + // Submit the form: + $form.get(0).submit(); + } + + }; + + $form.submit(function(event) { + // Disable the submit button to prevent repeated clicks: + $form.find('.submit').prop('disabled', true); + + // Request a token from Stripe: + Stripe.card.createToken($form, stripeResponseHandler); + + // Prevent the form from being submitted: + return false; + }); + + } +}; + +$(() => new Notebook.StripeHandler($("body.subscriptions.information"))); diff --git a/app/assets/javascripts/thredded_proxy.coffee b/app/assets/javascripts/thredded_proxy.coffee deleted file mode 100644 index 24f83d18..00000000 --- a/app/assets/javascripts/thredded_proxy.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# Place all the behaviors and hooks related to the matching controller here. -# All this logic will automatically be available in application.js. -# You can use CoffeeScript in this file: http://coffeescript.org/