add display_type configuration to external tools
this setting should allow tools to choose how they are displayed in the canvas interface. the new full width display removes the canvas sidebars, footer, and breadcrumbs. test plan: - install a tool with course_navigation and account_navigation extensions. - make sure the tool displays normally without a display_type configuration. - use a console to set display_type = 'full_width' in a tool's course_navigation settings. - the tool should display as a "full width" tool when viewed by the course navigation link. full width means without the left or right side bar, without breadcrumbs, and without a footer. the canvas header should still be displayed. - the tool should display normally when viewed by the account navigation link. - use the console to set the display_type = 'full_width' in the tool's top level settings. - tool tool should now display full width using the account navigation link. Change-Id: Idc19c0c96031bd80a45ce984241c23e4ce1efe78 Reviewed-on: https://gerrit.instructure.com/35160 Tested-by: Jenkins <jenkins@instructure.com> Reviewed-by: Brad Humphrey <brad@instructure.com> QA-Review: August Thornton <august@instructure.com> Product-Review: Jon Willesen <jonw@instructure.com>
This commit is contained in:
parent
dbb7b52e50
commit
79f84cb830
|
@ -27,6 +27,12 @@ class ExternalToolsController < ApplicationController
|
||||||
|
|
||||||
REDIS_PREFIX = 'external_tool:sessionless_launch:'
|
REDIS_PREFIX = 'external_tool:sessionless_launch:'
|
||||||
|
|
||||||
|
TOOL_DISPLAY_TEMPLATES = {
|
||||||
|
'full_width' => 'external_tools/full_width',
|
||||||
|
'in_context' => 'external_tools/tool_show',
|
||||||
|
'default' => 'external_tools/tool_show',
|
||||||
|
}
|
||||||
|
|
||||||
# @API List external tools
|
# @API List external tools
|
||||||
# Returns the paginated list of external tools for the current context.
|
# Returns the paginated list of external tools for the current context.
|
||||||
# See the get request docs for a single tool for a list of properties on an external tool.
|
# See the get request docs for a single tool for a list of properties on an external tool.
|
||||||
|
@ -296,7 +302,7 @@ class ExternalToolsController < ApplicationController
|
||||||
find_tool(params[:id], selection_type)
|
find_tool(params[:id], selection_type)
|
||||||
@active_tab = @tool.asset_string if @tool
|
@active_tab = @tool.asset_string if @tool
|
||||||
@show_embedded_chat = false if @tool.try(:tool_id) == 'chat'
|
@show_embedded_chat = false if @tool.try(:tool_id) == 'chat'
|
||||||
render_tool(selection_type)
|
render tool_launch(@tool, selection_type) if @tool
|
||||||
add_crumb(@context.name, named_context_url(@context, :context_url))
|
add_crumb(@context.name, named_context_url(@context, :context_url))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -314,7 +320,7 @@ class ExternalToolsController < ApplicationController
|
||||||
@tool_launch_type = 'self'
|
@tool_launch_type = 'self'
|
||||||
|
|
||||||
find_tool(params[:external_tool_id], selection_type)
|
find_tool(params[:external_tool_id], selection_type)
|
||||||
render_tool(selection_type)
|
render tool_launch(@tool, selection_type) if @tool
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_tool(id, selection_type)
|
def find_tool(id, selection_type)
|
||||||
|
@ -330,15 +336,13 @@ class ExternalToolsController < ApplicationController
|
||||||
redirect_to named_context_url(@context, :context_url)
|
redirect_to named_context_url(@context, :context_url)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
protected :find_tool
|
protected :find_tool
|
||||||
|
|
||||||
def render_tool(selection_type)
|
def tool_launch(tool, selection_type)
|
||||||
return unless @tool
|
@resource_title = tool.label_for(selection_type.to_sym)
|
||||||
@resource_title = @tool.label_for(selection_type.to_sym)
|
|
||||||
@return_url ||= url_for(@context)
|
@return_url ||= url_for(@context)
|
||||||
|
|
||||||
adapter = Lti::LtiOutboundAdapter.new(@tool, @current_user, @context)
|
adapter = Lti::LtiOutboundAdapter.new(tool, @current_user, @context)
|
||||||
adapter.prepare_tool_launch(@return_url, resource_type: selection_type, selected_html: params[:selection])
|
adapter.prepare_tool_launch(@return_url, resource_type: selection_type, selected_html: params[:selection])
|
||||||
if selection_type == 'homework_submission'
|
if selection_type == 'homework_submission'
|
||||||
@assignment = @context.assignments.active.find(params[:assignment_id])
|
@assignment = @context.assignments.active.find(params[:assignment_id])
|
||||||
|
@ -350,13 +354,19 @@ class ExternalToolsController < ApplicationController
|
||||||
@resource_url = adapter.launch_url
|
@resource_url = adapter.launch_url
|
||||||
|
|
||||||
resource_uri = URI.parse @resource_url
|
resource_uri = URI.parse @resource_url
|
||||||
@tool_id = @tool.tool_id || resource_uri.host || 'unknown'
|
@tool_id = tool.tool_id || resource_uri.host || 'unknown'
|
||||||
@tool_path = (resource_uri.path.empty? ? "/" : resource_uri.path)
|
@tool_path = (resource_uri.path.empty? ? "/" : resource_uri.path)
|
||||||
|
|
||||||
render :template => 'external_tools/tool_show'
|
return :template => find_display_type_template(tool, selection_type)
|
||||||
end
|
end
|
||||||
|
protected :tool_launch
|
||||||
|
|
||||||
|
def find_display_type_template(tool, selection_type)
|
||||||
|
TOOL_DISPLAY_TEMPLATES[tool.display_type(selection_type)] ||
|
||||||
|
TOOL_DISPLAY_TEMPLATES['default']
|
||||||
|
end
|
||||||
|
protected :find_display_type_template
|
||||||
|
|
||||||
protected :render_tool
|
|
||||||
|
|
||||||
# @API Create an external tool
|
# @API Create an external tool
|
||||||
# Create an external tool in the specified course/account.
|
# Create an external tool in the specified course/account.
|
||||||
|
|
|
@ -262,6 +262,10 @@ class ContextExternalTool < ActiveRecord::Base
|
||||||
write_attribute(:shared_secret, val) unless val.blank?
|
write_attribute(:shared_secret, val) unless val.blank?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def display_type(extension_type)
|
||||||
|
extension_setting(extension_type, :display_type) || 'in_context'
|
||||||
|
end
|
||||||
|
|
||||||
def extension_setting(type, property = nil)
|
def extension_setting(type, property = nil)
|
||||||
type = type.to_sym
|
type = type.to_sym
|
||||||
return settings[type] unless property && settings[type]
|
return settings[type] unless property && settings[type]
|
||||||
|
@ -583,6 +587,7 @@ class ContextExternalTool < ActiveRecord::Base
|
||||||
|
|
||||||
settings[setting][:url] = hash[:url] if hash[:url]
|
settings[setting][:url] = hash[:url] if hash[:url]
|
||||||
settings[setting][:text] = hash[:text] if hash[:text]
|
settings[setting][:text] = hash[:text] if hash[:text]
|
||||||
|
settings[setting][:display_type] = hash[:display_type] if hash[:display_type]
|
||||||
settings[setting][:custom_fields] = hash[:custom_fields] if hash[:custom_fields]
|
settings[setting][:custom_fields] = hash[:custom_fields] if hash[:custom_fields]
|
||||||
settings[setting][:enabled] = Canvas::Plugin.value_to_boolean(hash[:enabled]) if hash.has_key?(:enabled)
|
settings[setting][:enabled] = Canvas::Plugin.value_to_boolean(hash[:enabled]) if hash.has_key?(:enabled)
|
||||||
keys.each { |key| settings[setting][key] = hash[key] if hash.has_key?(key) }
|
keys.each { |key| settings[setting][key] = hash[key] if hash.has_key?(key) }
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
#footer {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main {
|
||||||
|
margin: 0;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
<form action="<%= @resource_url %>"
|
||||||
|
class="hide"
|
||||||
|
method="POST" target="tool_content"
|
||||||
|
id="tool_form"
|
||||||
|
data-tool-launch-type="<%= @tool_launch_type %>"
|
||||||
|
data-tool-id="<%= @tool_id %>"
|
||||||
|
data-tool-path="<%= @tool_path %>">
|
||||||
|
<% @tool_settings.each do |key, value| %>
|
||||||
|
<%= hidden_field_tag key, value %>
|
||||||
|
<% end %>
|
||||||
|
<% if @tag.try(:new_tab) %>
|
||||||
|
<div style="margin-bottom: 20px;">
|
||||||
|
<div class="load_tab">
|
||||||
|
<%= t :new_tab, "This tool needs to be loaded in a new browser window" %>
|
||||||
|
<div style="margin: 10px 0;">
|
||||||
|
<button class="btn" type="submit" data-expired_message="<%= t :new_tab_expired, "The session for this tool has expired. Please reload the page to access the tool again" %>"><%= t :load_tool_new_tab_button, "Load %{tool} in a new window", :tool => @tool.name %></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tab_loaded" style="display: none;">
|
||||||
|
<%= t :new_tab_loaded, "This tool was successfully loaded in a new browser window. Reload the page to access the tool again." %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% else %>
|
||||||
|
<button class="btn" type="submit"><%= t :load_tool_button, "Load %{tool}", :tool => @resource_title %></button>
|
||||||
|
<% end %>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<%= iframe("about:blank", :name => 'tool_content', :id => 'tool_content', :width => '100%', :height => '400') %>
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<% content_for :page_title do %><%= @resource_title %><% end %>
|
||||||
|
|
||||||
|
<%
|
||||||
|
@show_left_side = false
|
||||||
|
@body_classes << 'full-width'
|
||||||
|
crumbs.clear
|
||||||
|
%>
|
||||||
|
|
||||||
|
<% js_bundle 'legacy/external_tools_tool_show' %>
|
||||||
|
<% jammit_css :external_tool_full_width %>
|
||||||
|
|
||||||
|
<%= render partial: 'external_tools/tool_post_iframe' %>
|
|
@ -26,33 +26,8 @@
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<form action="<%= @resource_url %>"
|
<%= render :partial => 'external_tools/tool_post_iframe' %>
|
||||||
class="hide"
|
|
||||||
method="POST" target=tool_content
|
|
||||||
id="tool_form"
|
|
||||||
data-tool-launch-type="<%= @tool_launch_type %>"
|
|
||||||
data-tool-id="<%= @tool_id %>"
|
|
||||||
data-tool-path="<%= @tool_path %>">
|
|
||||||
<% @tool_settings.each do |key, value| %>
|
|
||||||
<%= hidden_field_tag key, value %>
|
|
||||||
<% end %>
|
|
||||||
<% if @tag.try(:new_tab) %>
|
|
||||||
<div style="margin-bottom: 20px;">
|
|
||||||
<div class="load_tab">
|
|
||||||
<%= t :new_tab, "This tool needs to be loaded in a new browser window" %>
|
|
||||||
<div style="margin: 10px 0;">
|
|
||||||
<button class="btn" type="submit" data-expired_message="<%= t :new_tab_expired, "The session for this tool has expired. Please reload the page to access the tool again" %>"><%= t :load_tool_new_tab_button, "Load %{tool} in a new window", :tool => @tool.name %></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tab_loaded" style="display: none;">
|
|
||||||
<%= t :new_tab_loaded, "This tool was successfully loaded in a new browser window. Reload the page to access the tool again." %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<% else %>
|
|
||||||
<button class="btn" type="submit"><%= t :load_tool_button, "Load %{tool}", :tool => @resource_title %></button>
|
|
||||||
<% end %>
|
|
||||||
</form>
|
|
||||||
<%= iframe("about:blank", :name => 'tool_content', :id => 'tool_content', :width => '100%', :height => '400') %>
|
|
||||||
<% if @tag %>
|
<% if @tag %>
|
||||||
<% if @tag.context.is_a?(Assignment) && (can_do(@tag.context, @current_user, :grade) || can_do(@tag.context.context, @current_user, :manage_assignments)) %>
|
<% if @tag.context.is_a?(Assignment) && (can_do(@tag.context, @current_user, :grade) || can_do(@tag.context.context, @current_user, :manage_assignments)) %>
|
||||||
<% content_for :right_side do %>
|
<% content_for :right_side do %>
|
||||||
|
|
|
@ -188,5 +188,7 @@ stylesheets:
|
||||||
- public/stylesheets/compiled/locale.css
|
- public/stylesheets/compiled/locale.css
|
||||||
mobile_auth:
|
mobile_auth:
|
||||||
- public/stylesheets/compiled/mobile_auth.css
|
- public/stylesheets/compiled/mobile_auth.css
|
||||||
|
external_tool_full_width:
|
||||||
|
- public/stylesheets/compiled/external_tools/full_width.css
|
||||||
|
|
||||||
<%= plugin_assets.anchors_yml %>
|
<%= plugin_assets.anchors_yml %>
|
|
@ -510,6 +510,28 @@ describe ContextExternalTool do
|
||||||
tool.resource_selection.should_not == nil
|
tool.resource_selection.should_not == nil
|
||||||
tool.editor_button.should_not == nil
|
tool.editor_button.should_not == nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "display_type" do
|
||||||
|
it "should be 'in_context' by default" do
|
||||||
|
tool.display_type(:course_navigation).should == 'in_context'
|
||||||
|
tool.course_navigation = {enabled: true}
|
||||||
|
tool.save!
|
||||||
|
tool.display_type(:course_navigation).should == 'in_context'
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should be configurable by a property" do
|
||||||
|
tool.course_navigation = { enabled: true }
|
||||||
|
tool.settings[:display_type] = "custom_display_type"
|
||||||
|
tool.save!
|
||||||
|
tool.display_type(:course_navigation).should == 'custom_display_type'
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should be configurable in extension" do
|
||||||
|
tool.course_navigation = {display_type: 'other_display_type'}
|
||||||
|
tool.save!
|
||||||
|
tool.display_type(:course_navigation).should == 'other_display_type'
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "change_domain" do
|
describe "change_domain" do
|
||||||
|
|
|
@ -725,6 +725,41 @@ describe "external tools" do
|
||||||
assert_flash_error_message(/couldn't find valid settings/i)
|
assert_flash_error_message(/couldn't find valid settings/i)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "display type" do
|
||||||
|
before do
|
||||||
|
@tool.course_navigation = {}
|
||||||
|
@tool.save!
|
||||||
|
end
|
||||||
|
|
||||||
|
it "defaults to normal display type" do
|
||||||
|
get "/courses/#{@course.id}/external_tools/#{@tool.id}"
|
||||||
|
f('#footer').should be_displayed
|
||||||
|
f('#left-side').should_not be_nil
|
||||||
|
f('#breadcrumbs').should_not be_nil
|
||||||
|
f('body').attribute('class').should_not include('full-width')
|
||||||
|
end
|
||||||
|
|
||||||
|
it "shows full width if top level property specified" do
|
||||||
|
@tool.settings[:display_type] = "full_width"
|
||||||
|
@tool.save!
|
||||||
|
get "/courses/#{@course.id}/external_tools/#{@tool.id}"
|
||||||
|
f('#footer').should_not be_displayed
|
||||||
|
f('#left-side').should be_nil
|
||||||
|
f('#breadcrumbs').should be_nil
|
||||||
|
f('body').attribute('class').should include('full-width')
|
||||||
|
end
|
||||||
|
|
||||||
|
it "shows full width if extension property specified" do
|
||||||
|
@tool.course_navigation[:display_type] = "full_width"
|
||||||
|
@tool.save!
|
||||||
|
get "/courses/#{@course.id}/external_tools/#{@tool.id}"
|
||||||
|
f('#footer').should_not be_displayed
|
||||||
|
f('#left-side').should be_nil
|
||||||
|
f('#breadcrumbs').should be_nil
|
||||||
|
f('body').attribute('class').should include('full-width')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
Loading…
Reference in New Issue