rewrite content_notices to use InstUI Alert

test plan:
 - enable redis
 - in the rails console, for a given course, do
   course.add_content_notice :import_in_progress, 1.hour
 - navigate to a page in that course as a user who has
   manage_content permission
 - the "One ore more items are currently being imported" message
   should appear at the top of the page and should be read
   to screenreaders

fixes ADMIN-2208

Change-Id: I39f2efe231c27e009aee0b13bbe26dc8fa37bad5
Reviewed-on: https://gerrit.instructure.com/175149
Tested-by: Jenkins
Reviewed-by: Ed Schiebel <eschiebel@instructure.com>
QA-Review: Daniel Sasaki <dsasaki@instructure.com>
Product-Review: Daniel Sasaki <dsasaki@instructure.com>
This commit is contained in:
Jeremy Stanley 2018-12-11 19:33:32 -07:00
parent 61d771b12c
commit c12de7d5f8
9 changed files with 75 additions and 50 deletions

View File

@ -332,6 +332,27 @@ class ApplicationController < ActionController::Base
end
helper_method :load_blueprint_courses_ui
def load_content_notices
if @context && @context.respond_to?(:content_notices)
notices = @context.content_notices(@current_user)
if notices.any?
js_env :CONTENT_NOTICES => notices.map { |notice|
{
tag: notice.tag,
variant: notice.variant || 'info',
text: notice.text.is_a?(Proc) ? notice.text.call : notice.text,
link_text: notice.link_text.is_a?(Proc) ? notice.link_text.call : notice.link_text,
link_target: notice.link_target.is_a?(Proc) ? notice.link_target.call(@context) : notice.link_target
}
}
js_bundle :content_notices
return true
end
end
false
end
helper_method :load_content_notices
def editing_restricted?(content, edit_type=:any)
return false unless content.respond_to?(:editing_restricted?)
content.editing_restricted?(edit_type)

View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2018 - present 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 <http://www.gnu.org/licenses/>.
*/
import React from 'react'
import ReactDOM from 'react-dom'
import Alert from '@instructure/ui-alerts/lib/components/Alert'
import Link from '@instructure/ui-elements/lib/components/Link'
import Text from '@instructure/ui-elements/lib/components/Text'
const container = document.getElementById('content_notice_container')
if (container && ENV.CONTENT_NOTICES.length > 0) {
const alerts = ENV.CONTENT_NOTICES.map(notice => {
let link = null
if (notice.link_text && notice.link_target) {
link = <Link href={notice.link_target}>{notice.link_text}</Link>
}
return <Alert key={notice.tag} variant={notice.variant} liveRegion={() => document.getElementById('flash_screenreader_holder')}>
<Text>{notice.text}</Text>&emsp;{link}
</Alert>
})
ReactDOM.render(alerts, container)
}

View File

@ -240,9 +240,9 @@ class Course < ActiveRecord::Base
include ContentNotices
define_content_notice :import_in_progress,
icon_class: 'icon-import-content',
alert_class: 'alert-info import-in-progress-notice',
template: 'courses/import_in_progress_notice',
text: -> { t('One or more items are currently being imported. They will be shown in the course below once they are available.') },
link_text: -> { t('Import Status') },
link_target: ->(course) { "/courses/#{course.to_param}/content_migrations" },
should_show: ->(course, user) do
course.grants_right?(user, :manage_content)
end

View File

@ -1,20 +0,0 @@
<%
# Copyright (C) 2014 - present 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 <http://www.gnu.org/licenses/>.
%>
<span><%= t('course_import_notice.text', 'One or more items are currently being imported. They will be shown in the course below once they are available.') %></span>
&emsp;<%= link_to t('course_import_notice.status_link', 'Import Status'), context_url(@context, :context_content_migrations_url) %>

View File

@ -75,6 +75,7 @@
content_for :head, include_common_stylesheets
load_blueprint_courses_ui
@has_content_notices = load_content_notices
-%>
<%= render :partial => "layouts/head" %>
<body class="<%= (@body_classes).uniq.join(" ") %> lato-font-not-loaded-yet">
@ -151,7 +152,7 @@
<% end %>
<div id="not_right_side" class="ic-app-main-content">
<div id="content-wrapper" class="ic-Layout-contentWrapper">
<%= render :partial => 'shared/content_notices' if @show_left_side && @context && @context.respond_to?(:content_notices) %>
<%= render :partial => 'shared/content_notices' if @has_content_notices && @show_left_side %>
<div id="content" class="ic-Layout-contentMain" role="main">
<%= yield %>
</div>

View File

@ -16,15 +16,4 @@
# with this program. If not, see <http://www.gnu.org/licenses/>.
%>
<% @context.content_notices(@current_user).each do |notice| %>
<div class="content_notice alert <%= notice.alert_class %>">
<% if notice.icon_class %>
<i class="<%= notice.icon_class %>"></i>
<% end %>
<% if notice.template %>
<%= render partial: notice.template %>
<% else %>
<%= notice.text.is_a?(Proc) ? notice.call : notice %>
<% end %>
</div>
<% end %>
<div id="content_notice_container"></div>

View File

@ -17,20 +17,20 @@
#
module ContentNotices
NOTICE_ATTRIBUTES = [:tag, :text, :template, :alert_class, :icon_class, :should_show]
NOTICE_ATTRIBUTES = [:tag, :text, :variant, :link_text, :link_target, :should_show]
class ContentNotice
attr_accessor *NOTICE_ATTRIBUTES
end
module ClassMethods
# opts must include exactly one of:
# text: string (or Proc that returns string) containing text for the notice
# template: erb partial containing html content for the notice
# opts must include:
# text: string (or Proc that returns string): text for the notice
# opts may optionally contain:
# alert_class: CSS class(es) for the notice box (suggestions: 'alert-info', 'alert-success', 'alert-error')
# icon_class: CSS class(es) for the icon (suggestions: 'icon-info', 'icon-check', 'icon-warning')
# should_show: callback that receives the context and user, and returns whether the notice should be displayed
# variant: string: InstUI alert variant ('info', 'success', 'error', 'warning'; default is 'info')
# link_text: string (or Proc that returns string): text for a link that follows the notice
# link_target: string (or Proc that takes the context and returns a string): the target for said link
# should_show: Proc: callback that receives the context and user, and returns whether the notice should be displayed
# see course.rb for example usage
def define_content_notice(tag, opts)
notice = ContentNotice.new

View File

@ -49,14 +49,12 @@ describe "course" do
migration.update_attribute(:workflow_state, 'importing')
get "/courses/#{@course.id}"
expect(response).to be_successful
body = Nokogiri::HTML(response.body)
expect(body.css('div.import-in-progress-notice')).not_to be_empty
expect(controller.js_env[:CONTENT_NOTICES].map { |cn| cn[:tag] }).to include :import_in_progress
migration.update_attribute(:workflow_state, 'imported')
get "/courses/#{@course.id}"
expect(response).to be_successful
body = Nokogiri::HTML(response.body)
expect(body.css('div.import-in-progress-notice')).to be_empty
expect((controller.js_env[:CONTENT_NOTICES] || []).map { |cn| cn[:tag] }).not_to include :import_in_progress
end
end
@ -72,8 +70,7 @@ describe "course" do
migration.update_attribute(:workflow_state, 'importing')
get "/courses/#{@course.id}"
expect(response).to be_successful
body = Nokogiri::HTML(response.body)
expect(body.css('div.import-in-progress-notice')).to be_empty
expect((controller.js_env[:CONTENT_NOTICES] || []).map { |cn| cn[:tag] }).not_to include :import_in_progress
end
end

View File

@ -23,7 +23,7 @@ describe ContentNotices do
def asset_string; "thing_1"; end
include ContentNotices
define_content_notice :foo, text: 'foo!'
define_content_notice :bar, template: 'some_template', should_show: ->(thing, user) { user == 'bob' }
define_content_notice :bar, text: 'baz', should_show: ->(thing, user) { user == 'bob' }
end
describe "content_notices" do