From fc4cc9ff465f740d1c669c7a884ce0a97e955cab Mon Sep 17 00:00:00 2001 From: Bracken Mosbacker Date: Wed, 6 Apr 2011 09:13:00 -0600 Subject: [PATCH] added ui for course exports refs #3396 Change-Id: I07c30535e042dada7c7d4174a7bb8148b7f6b1fb Reviewed-on: https://gerrit.instructure.com/3039 Tested-by: Hudson Reviewed-by: Brian Palmer --- app/controllers/application_controller.rb | 2 + app/controllers/content_exports_controller.rb | 95 +++++++++++++++ app/messages/_notes.txt | 3 + app/messages/content_export_failed.email.erb | 12 ++ .../content_export_finished.email.erb | 11 ++ app/models/content_export.rb | 111 ++++++++++++++++++ app/models/course.rb | 1 + app/views/content_exports/index.html.erb | 50 ++++++++ app/views/courses/course_details.html.erb | 1 + config/assets.yml | 2 + config/routes.rb | 9 ++ .../20110401214033_add_content_export.rb | 20 ++++ lib/canvas/cc/cc_exporter.rb | 66 ++++++++--- lib/canvas/cc/cc_helper.rb | 4 +- lib/canvas/cc/manifest.rb | 6 + lib/canvas/cc/resource.rb | 11 ++ .../cc/xsd/{cccv0p1.xsd => cccv1p0.xsd} | 22 ++-- lib/tasks/db_load_data.rake | 22 ++++ public/javascripts/content_exports.js | 111 ++++++++++++++++++ .../broadcast_policy/lib/broadcast_policy.rb | 2 +- 20 files changed, 530 insertions(+), 31 deletions(-) create mode 100644 app/controllers/content_exports_controller.rb create mode 100644 app/messages/content_export_failed.email.erb create mode 100644 app/messages/content_export_finished.email.erb create mode 100644 app/models/content_export.rb create mode 100644 app/views/content_exports/index.html.erb create mode 100644 db/migrate/20110401214033_add_content_export.rb rename lib/canvas/cc/xsd/{cccv0p1.xsd => cccv1p0.xsd} (97%) create mode 100644 public/javascripts/content_exports.js diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index f921576e62b..a37752f7244 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -237,6 +237,8 @@ class ApplicationController < ActionController::Base elsif request.path.match(/\A\/profile/) || request.path == '/' || request.path.match(/\A\/dashboard\/files/) || request.path.match(/\A\/calendar/) || request.path.match(/\A\/assignments/) || request.path.match(/\A\/files/) @context = @current_user @context_membership = @context + elsif params[:content_export_id] + @context = ContentExport.find(params[:content_export_id]) end if @context.try_rescue(:only_wiki_is_public) && params[:controller].match(/wiki/) && !@current_user && (!@context.is_a?(Course) || session[:enrollment_uuid_course_id] != @context.id) @show_left_side = false diff --git a/app/controllers/content_exports_controller.rb b/app/controllers/content_exports_controller.rb new file mode 100644 index 00000000000..0166247ef29 --- /dev/null +++ b/app/controllers/content_exports_controller.rb @@ -0,0 +1,95 @@ +# +# Copyright (C) 2011 Instructure, Inc. +# +# This file is part of Canvas. +# +# Canvas is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the Free +# Software Foundation, version 3 of the License. +# +# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +# details. +# +# You should have received a copy of the GNU Affero General Public License along +# with this program. If not, see . +# + +class ContentExportsController < ApplicationController + before_filter :require_context + before_filter { |c| c.active_tab = "settings" } + + def index + if authorized_action(@context, @current_user, :manage) + @exports = @context.content_exports.active + @current_export_id = nil + if export = @context.content_exports.running.first + @current_export_id = export.id + end + end + end + + def show + if authorized_action(@context, @current_user, :manage) + if export = @context.content_exports.find_by_id(params[:id]) + render_export(export) + else + render :json => {:errors => {:base => "Export does not exist"}}.to_json, :status => :bad_request + end + end + end + + def create + if authorized_action(@context, @current_user, :manage) + if @context.content_exports.running.count == 0 + export = ContentExport.new + export.course = @context + export.user = @current_user + export.workflow_state = 'created' + export.export_type = 'common_cartridge' + export.progress = 0 + if export.save + export.export_course + render_export(export) + else + render :json => {:error_message => "Couldn't create course export."}.to_json + end + else + # an export is already running, just return it + export = @context.content_exports.running.first + render_export(export) + end + end + end + + def destroy + if authorized_action(@context, @current_user, :manage) + if export = @context.content_exports.find_by_id(params[:id]) + export.destroy + render :json => {:success=>'true'}.to_json + else + render :json => {:errors => {:base => "Export does not exist"}}.to_json, :status => :bad_request + end + end + end + + def xml_schema + file = nil + if params[:version] + file = Rails.root + "lib/canvas/cc/xsd/#{params[:version]}.xsd" + end + + if File.exists?(file) + send_file(file, :type => 'text/xml', :disposition => 'inline') + else + render :template => 'shared/errors/404_message', :status => :bad_request + end + end + + private + + def render_export(export) + render :json => export.to_json(:only => [:id, :progress, :workflow_state],:methods => [:download_url, :error_message]) + end +end \ No newline at end of file diff --git a/app/messages/_notes.txt b/app/messages/_notes.txt index 027ea3bfea1..0a2af3784a7 100644 --- a/app/messages/_notes.txt +++ b/app/messages/_notes.txt @@ -1,3 +1,6 @@ +You need to register any new notifications in the DB. To do this edit the rake +task db:load_notifications in lib/tasks/db_load_data.rake + Since messages are parsed in a different thread than the request, they don't know the time_zone of the user by default. If you want to display formatted versions of a date or time, you could call force_zone from within the template diff --git a/app/messages/content_export_failed.email.erb b/app/messages/content_export_failed.email.erb new file mode 100644 index 00000000000..fa48d430f72 --- /dev/null +++ b/app/messages/content_export_failed.email.erb @@ -0,0 +1,12 @@ +<% define_content :link do %> + http://<%= HostUrl.context_host(asset.context) %>/<%= asset.context.class.to_s.downcase.pluralize %>/<%= asset.context_id %>/content_exports +<% end %> + +<% define_content :subject do %> + Course Export Failed: <%= asset.context.name %> +<% end %> + +There was a problem exporting the course "<%= asset.context.name %>". +Please notify your system administrator, and give them the following export identifier: "ContentExport:<%= asset.id %>". + +<%= content :link %> \ No newline at end of file diff --git a/app/messages/content_export_finished.email.erb b/app/messages/content_export_finished.email.erb new file mode 100644 index 00000000000..162c3a5edf7 --- /dev/null +++ b/app/messages/content_export_finished.email.erb @@ -0,0 +1,11 @@ +<% define_content :link do %> + http://<%= HostUrl.context_host(asset.context) %>/<%= asset.context.class.to_s.downcase.pluralize %>/<%= asset.context_id %>/content_exports +<% end %> + +<% define_content :subject do %> + Course Export Finished: <%= asset.context.name %> +<% end %> + +Your course export for "<%= asset.context.name %>" has finished. + +<%= content :link %> \ No newline at end of file diff --git a/app/models/content_export.rb b/app/models/content_export.rb new file mode 100644 index 00000000000..33a27291a2c --- /dev/null +++ b/app/models/content_export.rb @@ -0,0 +1,111 @@ +# +# Copyright (C) 2011 Instructure, Inc. +# +# This file is part of Canvas. +# +# Canvas is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the Free +# Software Foundation, version 3 of the License. +# +# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +# details. +# +# You should have received a copy of the GNU Affero General Public License along +# with this program. If not, see . +# + +class ContentExport < ActiveRecord::Base + include Workflow + belongs_to :course + belongs_to :user + belongs_to :attachment + has_many :attachments, :as => :context, :dependent => :destroy + has_a_broadcast_policy + serialize :settings + + workflow do + state :created + state :exporting + state :exported + state :failed + state :deleted + end + + set_broadcast_policy do |p| + p.dispatch :content_export_finished + p.to { [user] } + p.whenever {|record| + record.changed_state(:exported) + } + + p.dispatch :content_export_failed + p.to { [user] } + p.whenever {|record| + record.changed_state(:failed) + } + end + + def export_course + self.workflow_state = 'exporting' + self.save + begin + if Canvas::CC::CCExporter.export(self) + self.workflow_state = 'exported' + else + self.workflow_state = 'failed' + end + rescue + message = $!.to_s + stack = "#{$!}: #{$!.backtrace.join("\n")}" + add_error(message, stack) + self.workflow_state = 'failed' + ensure + self.save + end + end + handle_asynchronously :export_course, :priority => Delayed::LOW_PRIORITY + + def download_url + self.attachment ? self.attachment.authenticated_s3_url : nil + end + + def error_message + self.settings[:last_error] + end + + def add_error(message, stack) + self.settings[:error_messages] ||= [] + self.settings[:error_messages] << [message, stack] + self.settings[:last_error] = message + end + + def root_account + self.course.root_account + end + + def running? + ['created', 'exporting'].member? self.workflow_state + end + + alias_method :destroy!, :destroy + def destroy + self.workflow_state = 'deleted' + self.attachment.destroy! if self.attachment + save! + end + + def settings + read_attribute(:settings) || write_attribute(:settings,{}.with_indifferent_access) + end + + def fast_update_progress(val) + self.progress = val + ContentExport.update_all({:progress=>val}, "id=#{self.id}") + end + + named_scope :active, {:conditions => ['workflow_state != ?', 'deleted']} + named_scope :running, {:conditions => ['workflow_state IN (?)', ['created', 'exporting']]} + +end \ No newline at end of file diff --git a/app/models/course.rb b/app/models/course.rb index 8243f217677..a1b9c426b31 100644 --- a/app/models/course.rb +++ b/app/models/course.rb @@ -107,6 +107,7 @@ class Course < ActiveRecord::Base has_many :media_objects, :as => :context has_many :page_views, :as => :context has_many :role_overrides, :as => :context + has_many :content_exports attr_accessor :import_source before_save :assign_uuid diff --git a/app/views/content_exports/index.html.erb b/app/views/content_exports/index.html.erb new file mode 100644 index 00000000000..1d6eccfb179 --- /dev/null +++ b/app/views/content_exports/index.html.erb @@ -0,0 +1,50 @@ +<% add_crumb "Course Exports" %> +<% content_for :page_title do %>Course Exports<% end %> + +<% content_for :page_header do %> +

Course Exports

+<% end %> + +
+

Course Exports

+ +
+
+
+ +
+ <% @exports.each do |export| %> + <% unless export.running? %> + <% if export.workflow_state == 'exported' #&& export.attachment %> +

+ Course Export from <%= datetime_string export.created_at %>: + Click here to download +

+ <% end %> + <% end %> + <% end %> +
+ +
+ <% form_tag course_content_exports_path(@context.id), :id => "exporter_form" do %> +
+ +
+
+ <% end %> +
+ +
+
+
+ The export process has started. This can take awhile for large courses. + You can leave the page and you'll get an email when the export is complete. +
+
+ + <% if @current_export_id %> +
<%= @current_export_id %>
+ <% end %> +
+ +<% jammit_js :content_exports %> diff --git a/app/views/courses/course_details.html.erb b/app/views/courses/course_details.html.erb index 87c0da22017..706be6cc247 100644 --- a/app/views/courses/course_details.html.erb +++ b/app/views/courses/course_details.html.erb @@ -33,6 +33,7 @@ <%= image_tag "delete.png" %>End this Course <%= image_tag "file_multiple.png" %>Copy this Course <%= image_tag "file_multiple.png" %>Import Content into this Course + <%= image_tag "file_multiple.png" %>Export this Course <% end %> diff --git a/config/assets.yml b/config/assets.yml index 927a87989b6..3e5bc70a900 100644 --- a/config/assets.yml +++ b/config/assets.yml @@ -182,6 +182,8 @@ javascripts: - public/javascripts/link_enrollment.js plugins: - public/javascripts/plugins.js + content_exports: + - public/javascripts/content_exports.js stylesheets: common: diff --git a/config/routes.rb b/config/routes.rb index 5787255f67b..7e1e98753bb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -219,6 +219,7 @@ ActionController::Routing::Routes.draw do |map| m.last_redirect 'items/last', :controller => 'context_modules', :action => 'module_redirect', :last => 1 m.first_redirect 'items/first', :controller => 'context_modules', :action => 'module_redirect', :first => 1 end + course.resources :content_exports, :only => %w(create index destroy show) course.context_modules_assignment_info 'modules/items/assignment_info', :controller => 'context_modules', :action => 'content_tag_assignment_data', :conditions => {:method => :get} course.context_modules_item_redirect 'modules/items/:id', :controller => 'context_modules', :action => 'item_redirect', :conditions => {:method => :get} course.context_modules_item_details 'modules/items/sequence/:id', :controller => 'context_modules', :action => 'item_details', :conditions => {:method => :get} @@ -600,6 +601,14 @@ ActionController::Routing::Routes.draw do |map| map.saml_logout "saml_logout", :controller => "pseudonym_sessions", :action => "saml_logout" map.saml_meta_data "saml_meta_data", :controller => 'accounts', :action => 'saml_meta_data' + # Routes for course exports + map.connect 'xsd/:version.xsd', :controller => 'content_exports', :action => 'xml_schema' + map.resources :content_exports do |ce| + ce.resources :files do |file| + file.download 'download', :controller => 'files', :action => 'show', :download => '1' + end + end + Jammit::Routes.draw(map) # API routes diff --git a/db/migrate/20110401214033_add_content_export.rb b/db/migrate/20110401214033_add_content_export.rb new file mode 100644 index 00000000000..106b701e6c8 --- /dev/null +++ b/db/migrate/20110401214033_add_content_export.rb @@ -0,0 +1,20 @@ +class AddContentExport < ActiveRecord::Migration + def self.up + create_table :content_exports do |t| + t.integer :user_id, :limit => 8 + t.integer :course_id, :limit => 8 + t.integer :attachment_id, :limit => 8 + t.string :export_type + t.text :settings + t.float :progress + t.string :workflow_state + t.timestamps + end + add_index :content_exports, [:course_id] + add_index :content_exports, [:user_id] + end + + def self.down + drop_table :content_exports + end +end diff --git a/lib/canvas/cc/cc_exporter.rb b/lib/canvas/cc/cc_exporter.rb index 939567cd3ac..72a0b7c2544 100644 --- a/lib/canvas/cc/cc_exporter.rb +++ b/lib/canvas/cc/cc_exporter.rb @@ -20,17 +20,20 @@ module Canvas::CC attr_accessor :course, :user, :export_dir, :manifest, :zip_file - def initialize(course, user, opts={}) - @course = course - @user = user + def initialize(content_export, opts={}) + @content_export = content_export + @course = opts[:course] || @content_export.course + @user = opts[:user] || @content_export.user @export_dir = nil @manifest = nil @zip_file = nil + @zip_name = nil @logger = Rails.logger + @migration_config = Setting.from_config('external_migration') end - def self.export(course, user, opts={}) - exporter = CCExporter.new(course, user, opts) + def self.export(content_export, opts={}) + exporter = CCExporter.new(content_export, opts) exporter.export end @@ -41,25 +44,53 @@ module Canvas::CC @manifest = Manifest.new(self) @manifest.create_document @manifest.close - #copy all folder contents into zip file - #create attachment from zip file - #delete directory - rescue => e - #todo error handling - @logger.error e - #delete directory? + copy_all_to_zip + @zip_file.close + + if @content_export && File.exists?(@zip_path) + att = Attachment.new + att.context = @content_export + att.user = @content_export.user + up_data = ActionController::TestUploadedFile.new(@zip_path, Attachment.mimetype(@zip_path)) + att.uploaded_data = up_data + if att.save + @content_export.attachment = att + @content_export.save + end + end + rescue + message = $!.to_s + stack = "#{$!}: #{$!.backtrace.join("\n")}" + @content_export.add_error(message, stack) if @content_export + @logger.error $! + return false ensure @zip_file.close if @zip_file + if !@migration_config[:keep_after_complete] && File.directory?(@export_dir) + FileUtils::rm_rf(@export_dir) + end end + true + end + + def set_progress(progress) + @content_export.fast_update_progress(progress) if @content_export end private + + def copy_all_to_zip + Dir["#{@export_dir}/**/**"].each do |file| + next if File.basename(file) == @zip_name + file_path = file.sub(@export_dir+'/', '') + @zip_file.add(file_path, file) + end + end def create_export_dir slug = "common_cartridge_#{@course.id}_user_#{@user.id}" - config = Setting.from_config('external_migration') - if config && config[:data_folder] - folder = config[:data_folder] + if @migration_config && @migration_config[:data_folder] + folder = @migration_config[:data_folder] else folder = Dir.tmpdir end @@ -76,8 +107,9 @@ module Canvas::CC end def create_zip_file - path = File.join(@export_dir, "#{@course.name.to_url}-export.#{CCHelper::CC_EXTENSION}") - @zip_file = Zip::ZipFile.new(path, Zip::ZipFile::CREATE) + @zip_name = "#{@course.name.to_url}-export.#{CCHelper::CC_EXTENSION}" + @zip_path = File.join(@export_dir, @zip_name) + @zip_file = Zip::ZipFile.new(@zip_path, Zip::ZipFile::CREATE) end end diff --git a/lib/canvas/cc/cc_helper.rb b/lib/canvas/cc/cc_helper.rb index 751ff8dda02..8312477a75c 100644 --- a/lib/canvas/cc/cc_helper.rb +++ b/lib/canvas/cc/cc_helper.rb @@ -18,8 +18,8 @@ module Canvas::CC module CCHelper - CANVAS_NAMESPACE = 'http://www.instructure.com/xsd/cccv0p1' - XSD_URI = 'cccv0p1.xsd' + CANVAS_NAMESPACE = 'http://canvas.instructure.com/xsd/cccv1p0' + XSD_URI = 'http://canvas.instructure.com/xsd/cccv1p0.xsd' # IMS formats/types # The IMS documentation for Common Cartridge has conflicting values diff --git a/lib/canvas/cc/manifest.rb b/lib/canvas/cc/manifest.rb index 8c13bddcf0c..8e63b877c7f 100644 --- a/lib/canvas/cc/manifest.rb +++ b/lib/canvas/cc/manifest.rb @@ -62,8 +62,10 @@ module Canvas::CC manifest_node.metadata do |md| create_metadata(md) end + set_progress(5) Organization.create_organizations(self, manifest_node) + set_progress(10) Resource.create_resources(self, manifest_node) @@ -96,5 +98,9 @@ module Canvas::CC end end end + + def set_progress(progress) + @exporter.set_progress(progress) + end end end diff --git a/lib/canvas/cc/resource.rb b/lib/canvas/cc/resource.rb index 232b41b4a35..43a1ba86d74 100644 --- a/lib/canvas/cc/resource.rb +++ b/lib/canvas/cc/resource.rb @@ -44,15 +44,26 @@ module Canvas::CC @manifest_node.resources do |resources| @resources = resources add_canvas_non_cc_data + set_progress(15) add_wiki_pages + set_progress(30) add_assignments + set_progress(35) add_topics add_web_links + set_progress(40) add_course_files + set_progress(70) QTI::QTIGenerator.generate_qti(@manifest, resources) + set_progress(90) create_basic_lti_links #todo download kaltura videos? end end + + def set_progress(progress) + @manifest.set_progress(progress) + end + end end diff --git a/lib/canvas/cc/xsd/cccv0p1.xsd b/lib/canvas/cc/xsd/cccv1p0.xsd similarity index 97% rename from lib/canvas/cc/xsd/cccv0p1.xsd rename to lib/canvas/cc/xsd/cccv1p0.xsd index 402c7df26c5..bab40ce7494 100644 --- a/lib/canvas/cc/xsd/cccv0p1.xsd +++ b/lib/canvas/cc/xsd/cccv1p0.xsd @@ -1,6 +1,6 @@ - @@ -74,10 +74,10 @@ - - - - + + + + @@ -140,7 +140,7 @@ - + @@ -156,7 +156,7 @@ - + @@ -174,7 +174,7 @@ - + @@ -258,7 +258,7 @@ - + @@ -364,7 +364,7 @@ - + diff --git a/lib/tasks/db_load_data.rake b/lib/tasks/db_load_data.rake index 44d820c3561..49d3ea78ea4 100644 --- a/lib/tasks/db_load_data.rake +++ b/lib/tasks/db_load_data.rake @@ -188,6 +188,28 @@ namespace :db do }, %{ There was a problem importing <%= asset.migration_settings[:course_name] %> into <%= asset.context.name %>. Please notify your system administrator, and give them the following error code: "ContentMigration:<%= asset.id %>:<%= asset.progress %>". } + + create_notification 'ContentExport', 'Message', 0, + 'http://<%= HostUrl.default_host %>', %{ + Content Export Finished + + Course Export Finished: <%= asset.context.name %> + + Your course export for "<%= asset.context.name %>" has finished. + }, %{ + Your course export for "<%= asset.context.name %>" has finished. + } + + create_notification 'ContentExport', 'Message', 0, + 'http://<%= HostUrl.default_host %>', %{ + Content Export Failed + + Course Export failed: <%= asset.context.name %> + + There was a problem exporting the course "<%= asset.context.name %>". + }, %{ + There was a problem exporting the course "<%= asset.context.name %>". + } create_notification 'User', 'Other', 0, 'http://<%= HostUrl.default_host %>', %{ diff --git a/public/javascripts/content_exports.js b/public/javascripts/content_exports.js new file mode 100644 index 00000000000..2f85c5ad5fe --- /dev/null +++ b/public/javascripts/content_exports.js @@ -0,0 +1,111 @@ +/** + * Copyright (C) 2011 Instructure, Inc. + * + * This file is part of Canvas. + * + * Canvas is free software: you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by the Free + * Software Foundation, version 3 of the License. + * + * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +$(document).ready(function(event) { + var state = 'nothing'; + var current_id = null; + + function startPoll() { + $("#exporter_form").html("Processing
this may take a bit...
") + .attr('disabled', true); + $(".instruction").hide(); + $(".progress_bar_holder").slideDown(); + $(".export_progress").progressbar(); + state = "nothing"; + var fakeTickCount = 0; + var tick = function() { + if(state == "nothing") { + fakeTickCount++; + var progress = ($(".export_progress").progressbar('option', 'value') || 0) + 0.25; + if(fakeTickCount < 10) { + $(".export_progress").progressbar('option', 'value', progress); + } + setTimeout(tick, 2000); + } else { + state = "nothing"; + fakeTickCount = 0; + setTimeout(tick, 10000); + } + }; + var checkup = function() { + var lastProgress = null; + var waitTime = 1500; + $.ajaxJSON(location.href + "/" + current_id, 'GET', {}, function(data) { + state = "updating"; + var content_export = data.content_export; + var progress = 0; + if(content_export) { + progress = Math.max($(".export_progress").progressbar('option', 'value') || 0, content_export.progress); + $(".export_progress").progressbar('option', 'value', progress); + } + if(content_export.workflow_state == 'exported') { + $("#exporter_form").hide(); + $(".export_progress").progressbar('option', 'value', 100); + $(".progress_message").html("The course has been exported."); + $("#exports").append('

New Course Export: Click here to download

') + } else if(content_export.workflow_state == 'failed') { + code = "content_export_" + content_export.id; + $(".progress_bar_holder").hide(); + $("#exporter_form").hide(); + var message = "There was an error exporting your course. Please notify your system administrator and give them the following export identifier: \"" + code + "\""; + $(".export_messages .error_message").html(message); + $(".export_messages").show(); + } else { + if(progress == lastProgress) { + waitTime = Math.max(waitTime + 500, 30000); + } else { + waitTime = 1500; + } + lastProgress = progress; + setTimeout(checkup, 1500); + } + }, function() { + setTimeout(checkup, 3000); + }); + }; + setTimeout(checkup, 2000); + setTimeout(tick, 1000) + } + + $("#exporter_form").formSubmit({ + success: function(data) { + if(data && data.content_export) { + current_id = data.content_export.id + startPoll(); + } else { + //show error message + $(".export_messages .error_message").text(data.error_message); + $(".export_messages").show(); + } + }, + error: function(data) { + $(this).find(".submit_button").attr('disabled', false).text("Process Data"); + } + }); + + function check_if_exporting() { + //state = "checking"; + if( $('#current_export_id').size() ){ + //state = "nothing"; + current_id = $('#current_export_id').text() + startPoll(); + } + } + check_if_exporting(); + +}); diff --git a/vendor/plugins/broadcast_policy/lib/broadcast_policy.rb b/vendor/plugins/broadcast_policy/lib/broadcast_policy.rb index 2ce6beccb05..8e8f9ac0960 100644 --- a/vendor/plugins/broadcast_policy/lib/broadcast_policy.rb +++ b/vendor/plugins/broadcast_policy/lib/broadcast_policy.rb @@ -238,7 +238,7 @@ module Instructure #:nodoc: def broadcast_notifications return if @broadcasted @broadcasted = true - raise ArgumentError, "Block not supplied for #{self.class.to_s}" unless self.class.broadcast_policy_block + raise ArgumentError, "Broadcast Policy block not supplied for #{self.class.to_s}" unless self.class.broadcast_policy_block self.instance_eval &self.class.broadcast_policy_block self.broadcast_policy_list.each {|p| p.broadcast(self) } end