Skip to content

Commit 7e54f4f

Browse files
committed
basic lti custom fields
added UI for setting custom fields on tool creation fixes #5813 Change-Id: Ia3b46c040fb951c7c9c78692c627383a2a437be2 Reviewed-on: https://gerrit.instructure.com/5606 Tested-by: Hudson <hudson@instructure.com> Reviewed-by: Jacob Fugal <jacob@instructure.com>
1 parent ab1fddb commit 7e54f4f

6 files changed

Lines changed: 120 additions & 9 deletions

File tree

app/models/context_external_tool.rb

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ class ContextExternalTool < ActiveRecord::Base
22
include Workflow
33
has_many :content_tags, :as => :content
44
belongs_to :context, :polymorphic => true
5-
attr_accessible :privacy_level, :domain, :url, :shared_secret, :consumer_key, :name, :description, :custom_fields
5+
attr_accessible :privacy_level, :domain, :url, :shared_secret, :consumer_key, :name, :description, :custom_fields, :custom_fields_string
66
validates_presence_of :name
77
validates_presence_of :consumer_key
88
validates_presence_of :shared_secret
@@ -36,11 +36,23 @@ def privacy_level=(val)
3636
end
3737
end
3838

39-
def custom_fields=(hash)
40-
settings[:custom_fields] ||= {}
41-
hash.each do |key, val|
42-
settings[:custom_fields][key] = val.to_s
39+
def custom_fields_string
40+
(settings[:custom_fields] || {}).map{|key, val|
41+
"#{key}=#{val}"
42+
}.join("\n")
43+
end
44+
45+
def custom_fields_string=(str)
46+
hash = {}
47+
str.split(/\n/).each do |line|
48+
key, val = line.split(/=/)
49+
hash[key] = val if key.present? && val.present?
4350
end
51+
settings[:custom_fields] = hash
52+
end
53+
54+
def custom_fields=(hash)
55+
settings[:custom_fields] = hash if hash.is_a?(Hash)
4456
end
4557

4658
def shared_secret=(val)
@@ -169,6 +181,8 @@ def self.find_external_tool(url, context)
169181

170182
def self.serialization_excludes; [:shared_secret,:settings]; end
171183

184+
def self.serialization_methods; [:custom_fields_string]; end
185+
172186
def self.process_migration(data, migration)
173187
tools = data['external_tools'] ? data['external_tools']: []
174188
to_import = migration.to_import 'external_tools'

app/views/external_tools/_external_tool.html.erb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<a href="#" class="delete_tool_link" title="<%= t :delete_tool, "Delete Tool" %>"><%= image_tag "delete.png" %></a>
88
</div>
99
<div class="clear"></div>
10+
<div class="custom_fields_string" style="display: none;"><%= tool.try(:custom_fields_string) %></div>
1011
</div>
1112
<div class="content">
1213
<table class="formtable">

app/views/external_tools/_external_tools.html.erb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,17 @@
3838
</tr><tr>
3939
<td><%= f.blabel :privacy_level, :en => "Privacy" %></td>
4040
<td><%= f.select :privacy_level, [[t(:anonymous, "Anonymous"),'anonymous'],[t(:name_only, "Name Only"),'name_only'],[t(:public, "Public"),'public']] %></td>
41+
</tr><tr>
42+
<td colspan="2">
43+
<%= f.blabel :custom_fields_string, :en => "Custom Fields" %>
44+
<span style="font-size: 0.8em; color: #888;"><%= t('custom_fields_explanation', '(one per line, format: name=value)') %></span>
45+
<br/>
46+
<%= f.text_area :custom_fields_string, :style => "width: 550px; height: 30px;" %>
47+
</td>
4148
</tr><tr>
4249
<td colspan="2">
4350
<%= f.blabel :description, :en => "Description" %><br/>
44-
<%= f.text_area :description, :style => "width: 550px; height: 100px;" %>
51+
<%= f.text_area :description, :style => "width: 550px; height: 75px;" %>
4552
</td>
4653
</tr><tr>
4754
<td colspan="2">

public/javascripts/external_tools.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ $(document).ready(function() {
88
url: "",
99
description: "",
1010
name: "",
11+
custom_fields_string: "",
1112
privacy: "anonymous",
1213
consumer_key: "",
1314
shared_secret: ""
@@ -16,7 +17,7 @@ $(document).ready(function() {
1617
autoOpen: false,
1718
title: I18n.t('titles.edit_external_tool', "Edit External Tool"),
1819
width: 600,
19-
height: 400
20+
height: 420
2021
}).dialog('open');
2122
$dialog.find(".shared_secret_note").hide();
2223
$dialog.find("form")
@@ -57,7 +58,7 @@ $(document).ready(function() {
5758
$("#external_tools").delegate('.edit_tool_link', 'click', function(event) {
5859
event.preventDefault();
5960
var $tool = $(this).parents(".external_tool");
60-
var data = $tool.getTemplateData({textValues: ['name', 'description', 'domain', 'url', 'consumer_key'], dataValues: ['id', 'workflow_state']});
61+
var data = $tool.getTemplateData({textValues: ['name', 'description', 'domain', 'url', 'consumer_key', 'custom_fields_string'], dataValues: ['id', 'workflow_state']});
6162

6263
data.privacy_level = data.workflow_state;
6364
$("#external_tool_match_by").val(data.url ? 'url' : 'domain').change();
@@ -70,7 +71,7 @@ $(document).ready(function() {
7071
autoOpen: false,
7172
title: I18n.t('titles.edit_external_tool', "Edit External Tool"),
7273
width: 600,
73-
height: 400
74+
height: 420
7475
}).dialog('open');
7576
}).delegate('.delete_tool_link', 'click', function(event) {
7677
event.preventDefault();

spec/models/context_external_tool_spec.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,25 @@
108108
end
109109
end
110110

111+
describe "custom fields" do
112+
it "should parse custom_fields_string from a text field" do
113+
tool = @course.context_external_tools.create!(:name => "a", :url => "http://www.google.com", :consumer_key => '12345', :shared_secret => 'secret')
114+
tool.custom_fields_string=("a=1\nbT^@!#n_40=123\n\nc=")
115+
tool.settings[:custom_fields].should_not be_nil
116+
tool.settings[:custom_fields].keys.length.should == 2
117+
tool.settings[:custom_fields]['a'].should == '1'
118+
tool.settings[:custom_fields]['bT^@!#n_40'].should == '123'
119+
tool.settings[:custom_fields]['c'].should == nil
120+
end
121+
122+
it "should return custom_fields_string as a text-formatted field" do
123+
tool = @course.context_external_tools.create!(:name => "a", :url => "http://www.google.com", :consumer_key => '12345', :shared_secret => 'secret', :custom_fields => {'a' => '123', 'b' => '456'})
124+
tool.custom_fields_string.should == "a=123\nb=456"
125+
end
126+
127+
128+
end
129+
111130
describe "all_tools_for" do
112131
it "should retrieve all tools in alphabetical order" do
113132
@tools = []
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
require File.expand_path(File.dirname(__FILE__) + '/common')
2+
3+
describe "editing external tools" do
4+
it_should_behave_like "in-process server selenium tests"
5+
6+
it "should allow creating a new course external tool with custom fields" do
7+
course_with_teacher_logged_in
8+
get "/courses/#{@course.id}/settings"
9+
10+
keep_trying_until { driver.find_element(:css, "#tab-tools-link").displayed? }
11+
driver.find_element(:css, "#tab-tools-link").click
12+
driver.find_element(:css, ".add_tool_link").click
13+
driver.find_element(:css, "#external_tools_dialog").should be_displayed
14+
driver.find_element(:css, "#external_tool_name").send_keys "Tool"
15+
driver.find_element(:css, "#external_tool_consumer_key").send_keys "Key"
16+
driver.find_element(:css, "#external_tool_shared_secret").send_keys "Secret"
17+
driver.find_element(:css, "#external_tool_domain").send_keys "example.com"
18+
driver.find_element(:css, "#external_tool_custom_fields_string").send_keys "a=1\nb=123"
19+
driver.find_element(:css, "#external_tools_dialog .save_button").click
20+
21+
keep_trying_until { !driver.find_element(:css, "#external_tools_dialog").displayed? }
22+
23+
tool = ContextExternalTool.last
24+
driver.find_element(:css, "#external_tool_#{tool.id}").should be_displayed
25+
tool.should_not be_nil
26+
tool.name.should == "Tool"
27+
tool.consumer_key.should == "Key"
28+
tool.shared_secret.should == "Secret"
29+
tool.domain.should == "example.com"
30+
tool.settings[:custom_fields].should == {'a' => '1', 'b' => '123'}
31+
end
32+
33+
it "should allow editing an existing external tool with custom fields" do
34+
course_with_teacher_logged_in
35+
tool = @course.context_external_tools.create!(:name => "new tool", :consumer_key => "key", :shared_secret => "secret", :domain => 'example.com', :custom_fields => {'a' => '1', 'b' => '2'})
36+
get "/courses/#{@course.id}/settings"
37+
38+
keep_trying_until { driver.find_element(:css, "#tab-tools-link").displayed? }
39+
driver.find_element(:css, "#tab-tools-link").click
40+
tool_elem = driver.find_element(:css, "#external_tool_#{tool.id}")
41+
tool_elem.find_element(:css, ".edit_tool_link").click
42+
43+
driver.find_element(:css, "#external_tools_dialog").should be_displayed
44+
45+
driver.find_element(:css, "#external_tool_name").clear
46+
driver.find_element(:css, "#external_tool_consumer_key").clear
47+
driver.find_element(:css, "#external_tool_shared_secret").clear
48+
driver.find_element(:css, "#external_tool_domain").clear
49+
driver.find_element(:css, "#external_tool_custom_fields_string").clear
50+
51+
driver.find_element(:css, "#external_tool_name").send_keys "new tool (updated)"
52+
driver.find_element(:css, "#external_tool_consumer_key").send_keys "key (updated)"
53+
driver.find_element(:css, "#external_tool_shared_secret").send_keys "secret (updated)"
54+
driver.find_element(:css, "#external_tool_domain").send_keys "example2.com"
55+
driver.find_element(:css, "#external_tool_custom_fields_string").send_keys "a=9\nb=8"
56+
driver.find_element(:css, "#external_tools_dialog .save_button").click
57+
58+
keep_trying_until { !driver.find_element(:css, "#external_tools_dialog").displayed? }
59+
60+
tool_elem = driver.find_elements(:css, "#external_tools .external_tool").detect(&:displayed?)
61+
tool_elem.should_not be_nil
62+
tool.reload
63+
tool.name.should == "new tool (updated)"
64+
tool.consumer_key.should == "key (updated)"
65+
tool.shared_secret.should == "secret (updated)"
66+
tool.domain.should == "example2.com"
67+
tool.settings[:custom_fields].should == {'a' => '9', 'b' => '8'}
68+
end
69+
end

0 commit comments

Comments
 (0)