From d3564c18fd83ce02bf2c3daabbe61d30c864dc8d Mon Sep 17 00:00:00 2001 From: Andrew Cantino Date: Sat, 11 Apr 2015 21:17:56 -0700 Subject: [PATCH] allow FormConfigurable text areas to be syntax highlighted; allow JavaScriptAgent to be dry run --- app/assets/javascripts/ace.js.coffee | 3 ++ .../pages/agent-edit-page.js.coffee | 32 +++++++++++++++++-- .../pages/user-credential-page.js.coffee | 26 +++++++++++++++ .../javascripts/user_credentials.js.coffee | 29 ----------------- .../stylesheets/application.css.scss.erb | 6 ++-- app/concerns/form_configurable.rb | 2 +- app/helpers/application_helper.rb | 6 ++++ app/models/agents/java_script_agent.rb | 12 +++++-- app/models/agents/website_agent.rb | 2 +- .../form_configurable_agent_presenter.rb | 7 +++- app/views/agents/_form.html.erb | 9 ++++-- app/views/layouts/application.html.erb | 1 + app/views/user_credentials/_form.html.erb | 4 +-- config/environments/production.rb | 2 +- 14 files changed, 96 insertions(+), 45 deletions(-) create mode 100644 app/assets/javascripts/ace.js.coffee create mode 100644 app/assets/javascripts/pages/user-credential-page.js.coffee delete mode 100644 app/assets/javascripts/user_credentials.js.coffee diff --git a/app/assets/javascripts/ace.js.coffee b/app/assets/javascripts/ace.js.coffee new file mode 100644 index 00000000..8fe9c298 --- /dev/null +++ b/app/assets/javascripts/ace.js.coffee @@ -0,0 +1,3 @@ +#= require ace/ace +#= require ace/mode-javascript.js +#= require ace/mode-markdown.js diff --git a/app/assets/javascripts/pages/agent-edit-page.js.coffee b/app/assets/javascripts/pages/agent-edit-page.js.coffee index d227bd17..bfc5f927 100644 --- a/app/assets/javascripts/pages/agent-edit-page.js.coffee +++ b/app/assets/javascripts/pages/agent-edit-page.js.coffee @@ -2,6 +2,7 @@ class @AgentEditPage constructor: -> $("#agent_source_ids").on "change", @showEventDescriptions @showCorrectRegionsOnStartup() + $("form.agent-form").on "submit", => @updateFromEditors() # The type selector is only available on the new agent form. if $("#agent_type").length @@ -9,6 +10,7 @@ class @AgentEditPage @handleTypeChange(true) else @enableDryRunButton() + @buildAce() handleTypeChange: (firstTime) -> $(".event-descriptions").html("").hide() @@ -53,6 +55,7 @@ class @AgentEditPage window.jsonEditor = setupJsonEditor()[0] @enableDryRunButton() + @buildAce() window.initializeFormCompletable() @@ -126,17 +129,42 @@ class @AgentEditPage else @hideEventCreation() + buildAce: -> + $(".ace-editor").each -> + unless $(this).data('initialized') + $(this).data('initialized', true) + $source = $($(this).data('source')).hide() + syntax = $(this).data('syntax') + editor = ace.edit(this) + $(this).data('ace-editor', editor) + editor.getSession().setTabSize(2) + editor.getSession().setUseSoftTabs(true) + editor.getSession().setUseWrapMode(false) + editor.setTheme("ace/theme/chrome") + if syntax == 'javascript' + editor.getSession().setMode("ace/mode/javascript") + else + editor.getSession().setMode("ace/mode/text") + + editor.getSession().setValue($source.val()) + + updateFromEditors: -> + $(".ace-editor").each -> + $source = $($(this).data('source')) + $source.val($(this).data('ace-editor').getSession().getValue()) + enableDryRunButton: -> $(".agent-dry-run-button").prop('disabled', false).off().on "click", @invokeDryRun disableDryRunButton: -> $(".agent-dry-run-button").prop('disabled', true) - invokeDryRun: (e) -> + invokeDryRun: (e) => e.preventDefault() - button = this + button = e.target $(button).prop('disabled', true) $('body').css(cursor: 'progress') + @updateFromEditors() $.ajax type: 'POST', url: $(button).data('action-url'), dataType: 'json', data: $(button.form).serialize() .always => $("body").css(cursor: 'auto') diff --git a/app/assets/javascripts/pages/user-credential-page.js.coffee b/app/assets/javascripts/pages/user-credential-page.js.coffee new file mode 100644 index 00000000..257b7020 --- /dev/null +++ b/app/assets/javascripts/pages/user-credential-page.js.coffee @@ -0,0 +1,26 @@ +class @UserCredentialPage + constructor: -> + editor = ace.edit("ace-credential-value") + editor.getSession().setTabSize(2) + editor.getSession().setUseSoftTabs(true) + editor.getSession().setUseWrapMode(false) + editor.setTheme("ace/theme/chrome") + + setMode = -> + mode = $("#user_credential_mode").val() + if mode == 'java_script' + editor.getSession().setMode("ace/mode/javascript") + else + editor.getSession().setMode("ace/mode/text") + + setMode() + $("#user_credential_mode").on 'change', setMode + + $textarea = $('#user_credential_credential_value').hide() + editor.getSession().setValue($textarea.val()) + + $textarea.closest('form').on 'submit', -> + $textarea.val(editor.getSession().getValue()) + +$ -> + Utils.registerPage(UserCredentialPage, forPathsMatching: /^user_credentials\/\d+/) \ No newline at end of file diff --git a/app/assets/javascripts/user_credentials.js.coffee b/app/assets/javascripts/user_credentials.js.coffee deleted file mode 100644 index c27a2bcb..00000000 --- a/app/assets/javascripts/user_credentials.js.coffee +++ /dev/null @@ -1,29 +0,0 @@ -#= require ace/ace -#= require ace/mode-javascript.js -#= require ace/mode-markdown.js -#= require_self - -# This is not included in the core application.js bundle. - -$ -> - editor = ace.edit("ace-credential-value") - editor.getSession().setTabSize(2) - editor.getSession().setUseSoftTabs(true) - editor.getSession().setUseWrapMode(false) - editor.setTheme("ace/theme/chrome") - - setMode = -> - mode = $("#user_credential_mode").val() - if mode == 'java_script' - editor.getSession().setMode("ace/mode/javascript") - else - editor.getSession().setMode("ace/mode/text") - - setMode() - $("#user_credential_mode").on 'change', setMode - - $textarea = $('#user_credential_credential_value').hide() - editor.getSession().setValue($textarea.val()) - - $textarea.closest('form').on 'submit', -> - $textarea.val(editor.getSession().getValue()) \ No newline at end of file diff --git a/app/assets/stylesheets/application.css.scss.erb b/app/assets/stylesheets/application.css.scss.erb index 5462fcab..625994cf 100644 --- a/app/assets/stylesheets/application.css.scss.erb +++ b/app/assets/stylesheets/application.css.scss.erb @@ -172,12 +172,12 @@ span.not-applicable:after { font-weight: bold; } -// Credentials +// Credentials and Ace Editor -#ace-credential-value { +#ace-credential-value, .ace-editor { position: relative; width: 940px; - height: 400px; + height: 300px; } // Disabled diff --git a/app/concerns/form_configurable.rb b/app/concerns/form_configurable.rb index 22f3b9a6..ce4afba1 100644 --- a/app/concerns/form_configurable.rb +++ b/app/concerns/form_configurable.rb @@ -32,7 +32,7 @@ module FormConfigurable options = args.extract_options!.reverse_merge(roles: [], type: :string) if args.all? { |arg| arg.is_a?(Symbol) } - options.assert_valid_keys([:type, :roles, :values]) + options.assert_valid_keys([:type, :roles, :values, :syntax]) end if options[:type] == :array && (options[:values].blank? || !options[:values].is_a?(Array)) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 543e9a0b..d400d049 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -84,6 +84,12 @@ module ApplicationHelper ].join.html_safe, class: "label label-default label-service service-#{service.provider}" end + def load_ace_editor! + unless content_for?(:ace_editor_script) + content_for :ace_editor_script, javascript_include_tag('ace') + end + end + def highlighted?(id) @highlighted_ranges ||= case value = params[:hl].presence diff --git a/app/models/agents/java_script_agent.rb b/app/models/agents/java_script_agent.rb index b9fe7c9c..eb7af7d7 100644 --- a/app/models/agents/java_script_agent.rb +++ b/app/models/agents/java_script_agent.rb @@ -3,6 +3,10 @@ require 'cgi' module Agents class JavaScriptAgent < Agent + include FormConfigurable + + can_dry_run! + default_schedule "never" description <<-MD @@ -23,6 +27,10 @@ module Agents * `this.error(message)` MD + form_configurable :code, type: :text, syntax: :javascript + form_configurable :expected_receive_period_in_days + form_configurable :expected_update_period_in_days + def validate_options cred_name = credential_referenced_by_code if cred_name @@ -67,7 +75,7 @@ module Agents this.memory('callCount', callCount + 1); } }; - + Agent.receive = function() { var events = this.incomingEvents(); for(var i = 0; i < events.length; i++) { @@ -77,7 +85,7 @@ module Agents JS { - "code" => js_code.gsub(/[\n\r\t]/, '').strip, + "code" => Utils.unindent(js_code), 'expected_receive_period_in_days' => "2", 'expected_update_period_in_days' => "2" } diff --git a/app/models/agents/website_agent.rb b/app/models/agents/website_agent.rb index f0feb070..f86c9c7c 100644 --- a/app/models/agents/website_agent.rb +++ b/app/models/agents/website_agent.rb @@ -376,7 +376,7 @@ module Agents end end - # Wraps Faraday::Utilsa::Headers + # Wraps Faraday::Utils::Headers class HeaderDrop < LiquidDroppable::Drop def before_method(name) @object[name.tr('_', '-')] diff --git a/app/presenters/form_configurable_agent_presenter.rb b/app/presenters/form_configurable_agent_presenter.rb index d4f2d405..d84c9f65 100644 --- a/app/presenters/form_configurable_agent_presenter.rb +++ b/app/presenters/form_configurable_agent_presenter.rb @@ -20,7 +20,12 @@ class FormConfigurableAgentPresenter < Decorator case data[:type] when :text - @view.text_area_tag "agent[options][#{attribute}]", value, html_options.merge(class: 'form-control', rows: 3) + @view.content_tag 'div' do + @view.concat @view.text_area_tag("agent[options][#{attribute}]", value, html_options.merge(class: 'form-control', rows: 3)) + if data[:syntax].present? + @view.concat @view.content_tag('div', '', class: 'ace-editor', data: { source: "[name='agent[options][#{attribute}]']", syntax: data[:syntax] }) + end + end when :boolean @view.content_tag 'div' do @view.concat(@view.content_tag('label', class: 'radio-inline') do diff --git a/app/views/agents/_form.html.erb b/app/views/agents/_form.html.erb index 51e38900..6c0e60d7 100644 --- a/app/views/agents/_form.html.erb +++ b/app/views/agents/_form.html.erb @@ -1,3 +1,5 @@ +<% load_ace_editor! %> + <% if @agent.errors.any? %>

<%= pluralize(@agent.errors.count, "error") %> prohibited this Agent from being saved:

@@ -8,9 +10,10 @@ <% end %> <%= form_for(@agent, - :as => :agent, - :url => @agent.new_record? ? agents_path : agent_path(@agent), - :method => @agent.new_record? ? "POST" : "PUT") do |f| %> + as: :agent, + url: @agent.new_record? ? agents_path : agent_path(@agent), + method: @agent.new_record? ? "POST" : "PUT", + html: { class: 'agent-form' }) do |f| %>
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index c669523b..4537970f 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -9,6 +9,7 @@ <%= stylesheet_link_tag "application", :media => "all" %> <%= javascript_include_tag "application" %> <%= csrf_meta_tags %> + <%= yield(:ace_editor_script) %> <%= yield(:head) %> diff --git a/app/views/user_credentials/_form.html.erb b/app/views/user_credentials/_form.html.erb index 2aaa983d..86c42b98 100644 --- a/app/views/user_credentials/_form.html.erb +++ b/app/views/user_credentials/_form.html.erb @@ -1,3 +1,5 @@ +<% load_ace_editor! %> + <%= form_for(@user_credential, :method => @user_credential.new_record? ? "POST" : "PUT") do |f| %> <% if @user_credential.errors.any? %>
@@ -40,5 +42,3 @@
<% end %> - -<%= javascript_include_tag "user_credentials" %> diff --git a/config/environments/production.rb b/config/environments/production.rb index 81235320..9393fe32 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -63,7 +63,7 @@ Huginn::Application.configure do end # Precompile additional assets (application.js.coffee.erb, application.css, and all non-JS/CSS are already added) - config.assets.precompile += %w( diagram.js graphing.js map_marker.js user_credentials.js ) + config.assets.precompile += %w( diagram.js graphing.js map_marker.js ace.js ) # Ignore bad email addresses and do not raise email delivery errors. # Set this to true and configure the email server for immediate delivery to raise delivery errors.