Merge branch 'master' into dev/grading-periods-update

Change-Id: Idaf66797a745b9c43aeb70361d476b621799a43f
This commit is contained in:
Spencer Olson 2016-05-16 13:39:41 -04:00
commit 3ba3d62761
69 changed files with 998 additions and 649 deletions

View File

@ -110,9 +110,6 @@ define [
htmlUrl: =>
@get 'url'
togglePostToSISUrl: =>
@get 'toggle_post_to_sis_url'
defaultDates: =>
group = new DateGroup
due_at: @get("due_at")

View File

@ -0,0 +1,67 @@
define [
'i18n!assignments',
'Backbone',
'jquery',
'jst/_sisButton'
], (I18n, Backbone, $, template) ->
class SisButtonView extends Backbone.View
template: template
tagName: 'span'
className: 'sis-button'
events:
'click': 'togglePostToSIS'
SIS_ATTRIBUTES = {
enabled: {
src: '/images/svg-icons/svg_icon_post_to_sis_active.svg',
description: I18n.t('Post grade to SIS enabled. Click to toggle.'),
label: I18n.t('The grade for this assignment will sync to the student information system.'),
},
disabled: {
src: '/images/svg-icons/svg_icon_post_to_sis.svg',
description: I18n.t('Post grade to SIS disabled. Click to toggle.'),
label: I18n.t('The grade for this assignment will not sync to the student information system.')
}
}
setAttributes: ->
newSisAttributes = @sisAttributes()
@$input.attr({
'src': newSisAttributes['src'],
'alt': newSisAttributes['description'],
'title': newSisAttributes['description']
})
@$label.text(newSisAttributes['label'])
togglePostToSIS: (e) =>
e.preventDefault()
sisUrl = @model.get('toggle_post_to_sis_url')
c = @model.postToSIS()
@model.postToSIS(!c)
if sisUrl
@model.save({}, {
type: 'POST',
url: sisUrl,
success: =>
@setAttributes()
})
else
@model.save({}, {
success: =>
@setAttributes()
})
sisAttributes: =>
sisStatus = if @model.postToSIS() then "enabled" else "disabled"
SIS_ATTRIBUTES[sisStatus]
render: ->
super
labelId = 'sis-status-label-'+ @model.id
@$label = @$el.find('label')
@$input = @$el.find('input')
@$input.attr('aria-describedby': labelId)
@$label.attr('id', labelId)
@setAttributes()

View File

@ -7,6 +7,7 @@ define [
'compiled/views/assignments/DateDueColumnView'
'compiled/views/assignments/DateAvailableColumnView'
'compiled/views/assignments/CreateAssignmentView'
'compiled/views/SisButtonView'
'compiled/views/MoveDialogView'
'compiled/fn/preventDefault'
'jst/assignments/AssignmentListItem'
@ -16,7 +17,7 @@ define [
'jqueryui/tooltip'
'compiled/behaviors/tooltip'
'compiled/jquery.rails_flash_notifications'
], (I18n, Backbone, $, _, PublishIconView, DateDueColumnView, DateAvailableColumnView, CreateAssignmentView, MoveDialogView, preventDefault, template, scoreTemplate, round, AssignmentKeyBindingsMixin) ->
], (I18n, Backbone, $, _, PublishIconView, DateDueColumnView, DateAvailableColumnView, CreateAssignmentView, SisButtonView, MoveDialogView, preventDefault, template, scoreTemplate, round, AssignmentKeyBindingsMixin) ->
class AssignmentListItemView extends Backbone.View
@mixin AssignmentKeyBindingsMixin
@ -28,7 +29,8 @@ define [
@child 'dateDueColumnView', '[data-view=date-due]'
@child 'dateAvailableColumnView', '[data-view=date-available]'
@child 'editAssignmentView', '[data-view=edit-assignment]'
@child 'moveAssignmentView', '[data-view=moveAssignment]'
@child 'sisButtonView', '[data-view=sis-button]'
@child 'moveAssignmentView', '[data-view=moveAssignment]'
els:
'.edit_assignment': '$editAssignmentButton'
@ -38,7 +40,6 @@ define [
'click .delete_assignment': 'onDelete'
'click .tooltip_link': preventDefault ->
'keydown': 'handleKeys'
'click .post-to-sis-status': 'togglePostToSIS'
messages:
confirm: I18n.t('confirms.delete_assignment', 'Are you sure you want to delete this assignment?')
@ -64,6 +65,7 @@ define [
initializeChildViews: ->
@publishIconView = false
@sisButtonView = false
@editAssignmentView = false
@dateAvailableColumnView = false
@moveAssignmentView = false
@ -85,6 +87,9 @@ define [
closeTarget: @$el.find('a[id*=manage_link]')
saveURL: -> "#{ENV.URLS.assignment_sort_base_url}/#{@parentListView.value()}/reorder"
if @model.postToSISEnabled()
@sisButtonView = new SisButtonView(model: @model)
@dateDueColumnView = new DateDueColumnView(model: @model)
@dateAvailableColumnView = new DateAvailableColumnView(model: @model)
@ -95,6 +100,7 @@ define [
render: ->
@toggleHidden(@model, @model.get('hidden'))
@publishIconView.remove() if @publishIconView
@sisButtonView.remove() if @sisButtonView
@editAssignmentView.remove() if @editAssignmentView
@dateDueColumnView.remove() if @dateDueColumnView
@dateAvailableColumnView.remove() if @dateAvailableColumnView
@ -267,27 +273,6 @@ define [
editItem: =>
@$("#assignment_#{@model.id}_settings_edit_item").click()
togglePostToSIS: (e) =>
c = @model.postToSIS()
@model.postToSIS(!c)
e.preventDefault()
$t = $(e.currentTarget)
@model.save({}, {
success: =>
if c
$t.removeClass('post-to-sis-status enabled')
$t.addClass('post-to-sis-status disabled')
$t.find('.icon-post-to-sis').prop('title', I18n.t("Post grade to SIS disabled. Click to toggle."))
.prop('src', '/images/svg-icons/svg_icon_post_to_sis.svg')
$t.find('.screenreader-only').text(I18n.t("The grade for this assignment will not sync to the student information system. Click here to toggle this setting."))
else
$t.removeClass('post-to-sis-status disabled')
$t.addClass('post-to-sis-status enabled')
$t.find('.icon-post-to-sis').prop('title', I18n.t("Post grade to SIS enabled. Click to toggle."))
.prop('src', '/images/svg-icons/svg_icon_post_to_sis_active.svg')
$t.find('.screenreader-only').text(I18n.t("The grade for this assignment will sync to the student information system. Click here to toggle this setting."))
})
deleteItem: =>
@$("#assignment_#{@model.id}_settings_delete_item").click()

View File

@ -20,6 +20,24 @@ define [
if ENV.canManageCourse
@collection.fetch()
render: ->
super
@refreshTabs()
refreshTabs: ->
$tabs = $('#group_categories_tabs')
$tabs.tabs().show()
$tabs.tabs
beforeActivate: (event, ui) ->
ui.newTab.hasClass('static')
$groupTabs = $tabs.find('li').not('.static')
$groupTabs.find('a').unbind()
$groupTabs.on 'keydown', (event) ->
event.stopPropagation()
if event.keyCode == 13 or event.keyCode == 32
window.location.href = $(this).find('a').attr('href')
toJSON: ->
json = {}
json.collection = super

View File

@ -64,7 +64,6 @@ define [
showEditForm: ->
@$el.addClass('editing').removeClass('not-editing')
@$('.profile_links').removeClass('span6')
initEdit: ->
if @options.links?.length
@ -77,7 +76,6 @@ define [
cancelEditProfile: ->
@$el.addClass('not-editing').removeClass('editing')
@$('.profile_links').addClass('span6')
##
# Event handler that can also be called manually.

View File

@ -6,8 +6,9 @@ define [
'compiled/views/PublishIconView'
'compiled/views/assignments/DateDueColumnView'
'compiled/views/assignments/DateAvailableColumnView'
'compiled/views/SisButtonView'
'jst/quizzes/QuizItemView'
], (I18n, $, _, Backbone, PublishIconView, DateDueColumnView, DateAvailableColumnView, template) ->
], (I18n, $, _, Backbone, PublishIconView, DateDueColumnView, DateAvailableColumnView, SisButtonView, template) ->
class ItemView extends Backbone.View
@ -19,11 +20,11 @@ define [
@child 'publishIconView', '[data-view=publish-icon]'
@child 'dateDueColumnView', '[data-view=date-due]'
@child 'dateAvailableColumnView', '[data-view=date-available]'
@child 'sisButtonView', '[data-view=sis-button]'
events:
'click': 'clickRow'
'click .delete-item': 'onDelete'
'click .post-to-sis-status': 'togglePostToSIS'
messages:
confirm: I18n.t('confirms.delete_quiz', 'Are you sure you want to delete this quiz?')
@ -38,9 +39,12 @@ define [
initializeChildViews: ->
@publishIconView = false
@sisButtonView = false
if @canManage()
@publishIconView = new PublishIconView(model: @model)
if @model.postToSISEnabled()
@sisButtonView = new SisButtonView(model: @model)
@dateDueColumnView = new DateDueColumnView(model: @model)
@dateAvailableColumnView = new DateAvailableColumnView(model: @model)
@ -82,25 +86,6 @@ define [
updatePublishState: =>
@$('.ig-row').toggleClass('ig-published', @model.get('published'))
togglePostToSIS: (e) =>
c = @model.postToSIS()
@model.postToSIS(!c)
e.preventDefault()
$t = $(e.currentTarget)
@model.save({}, { type: 'POST', url: @model.togglePostToSISUrl(),
success: =>
if c
$t.removeClass('post-to-sis-status enabled')
$t.addClass('post-to-sis-status disabled')
$t.find('.icon-post-to-sis').prop('title', I18n.t("Post grade to SIS disabled. Click to toggle."))
$t.find('.screenreader-only').text(I18n.t("The grade for this assignment will not sync to the student information system. Click here to toggle this setting."))
else
$t.removeClass('post-to-sis-status disabled')
$t.addClass('post-to-sis-status enabled')
$t.find('.icon-post-to-sis').prop('title', I18n.t("Post grade to SIS enabled. Click to toggle."))
$t.find('.screenreader-only').text(I18n.t("The grade for this assignment will sync to the student information system. Click here to toggle this setting."))
})
canManage: ->
ENV.PERMISSIONS.manage

View File

@ -322,7 +322,7 @@
# "type": "boolean"
# },
# "external_tool_tag_attributes": {
# "description": "(Optional) assignment's settings for external tools if submission_types include 'external_tool'. Only url and new_tab are included. Use the 'External Tools' API if you need more information about an external tool.",
# "description": "(Optional) assignment's settings for external tools if submission_types include 'external_tool'. Only url and new_tab are included (new_tab defaults to false). Use the 'External Tools' API if you need more information about an external tool.",
# "$ref": "ExternalToolTagAttributes"
# },
# "peer_reviews": {
@ -768,14 +768,8 @@ class AssignmentsApiController < ApplicationController
# assign scores to each member of the group.
#
# @argument assignment[external_tool_tag_attributes]
# Hash of attributes if submission_types is ["external_tool"]
# Example:
# external_tool_tag_attributes: {
# // url to the external tool
# url: "http://instructure.com",
# // create a new tab for the module, defaults to false.
# new_tab: false
# }
# Hash of external tool parameters if submission_types is ["external_tool"].
# See Assignment object definition for format.
#
# @argument assignment[points_possible] [Float]
# The maximum points possible on the assignment.
@ -912,14 +906,8 @@ class AssignmentsApiController < ApplicationController
# assign scores to each member of the group.
#
# @argument assignment[external_tool_tag_attributes]
# Hash of attributes if submission_types is ["external_tool"]
# Example:
# external_tool_tag_attributes: {
# // url to the external tool
# url: "http://instructure.com",
# // create a new tab for the module, defaults to false.
# new_tab: false
# }
# Hash of external tool parameters if submission_types is ["external_tool"].
# See Assignment object definition for format.
#
# @argument assignment[points_possible] [Float]
# The maximum points possible on the assignment.

View File

@ -493,6 +493,7 @@ class GradebooksController < ApplicationController
end
def submissions_zip_upload
return unless authorized_action(@context, @current_user, :manage_grades)
unless @context.allows_gradebook_uploads?
flash[:error] = t('errors.not_allowed', "This course does not allow score uploads.")
redirect_to named_context_url(@context, :context_assignment_url, @assignment.id)

View File

@ -172,7 +172,7 @@ class ProfileController < ApplicationController
known_user = @user_data[:common_contexts].present?
if @user_data[:known_user] # if you can message them, you can see the profile
add_crumb(t('crumbs.settings_frd', "%{user}'s settings", :user => @user.short_name), user_profile_path(@user))
add_crumb(t('crumbs.settings_frd', "%{user}'s Profile", :user => @user.short_name), user_profile_path(@user))
render
else
render :unauthorized

View File

@ -414,7 +414,7 @@ module ApplicationHelper
#
# Returns an HTML string.
def sidebar_button(url, label, img = nil)
link_to(url, :class => 'btn button-sidebar-wide') do
link_to(url) do
img ? ("<i class='icon-" + img + "'></i> ").html_safe + label : label
end
end

View File

@ -23,9 +23,10 @@
<td valign="top"><%= date_string(asset.start_at, asset.end_at, :no_words) %></td>
</tr>
<tr>
<td style="padding-right: 10px;" valign="top"><%= asset.participant_type == 'Group' ?
t(:group_signup, "Group (%{group_category})", :group_category => asset.sub_contexts.first.name) :
t(:individual_signup, "Individual") %></td>
<td style="padding-right: 10px;" valign="top"><%= t "Signup Type" %>:</td>
<td valign="top"><%= asset.participant_type == 'Group' ?
t(:group_signup, "Group (%{group_category})", :group_category => asset.sub_contexts.first.name) :
t(:individual_signup, "Individual") %></td>
</tr>
<tr>
<td style="padding-right: 10px;" valign="top"><%= t :course, "Course" %>:</td>

View File

@ -1180,6 +1180,22 @@ class Attachment < ActiveRecord::Base
true
end
def make_childless
child = children.take
return unless child
child.root_attachment_id = nil
child.filename ||= filename
if Attachment.s3_storage?
if s3object.exists? && !child.s3object.exists?
s3object.copy_to(child.s3object)
end
else
child.uploaded_data = open
end
child.save!
Attachment.where(root_attachment_id: self).where.not(id: child).update_all(root_attachment_id: child)
end
def restore
self.file_state = 'available'
self.save

View File

@ -62,7 +62,7 @@ module BroadcastPolicies
!assignment.muted? &&
assignment.published? &&
submission.quiz_submission.nil? &&
user_active_invited_or_concluded?
user_active_or_invited?
end
def assignment
@ -102,11 +102,8 @@ module BroadcastPolicies
AssignmentStudentVisibility.where(assignment_id: submission.assignment_id, user_id: submission.user_id).any?
end
def user_active_invited_or_concluded?
course.all_student_enrollments.
where("enrollments.workflow_state NOT IN ('deleted','inactive','rejected')").
where(user_id: submission.user_id).
exists?
def user_active_or_invited?
course.student_enrollments.where(user_id: submission.user_id).to_a.any?{|e| e.active? || e.invited?}
end
end
end

View File

@ -35,7 +35,7 @@ class EnrollmentTerm < ActiveRecord::Base
before_validation :verify_unique_sis_source_id
before_save :update_courses_later_if_necessary
before_save :destroy_orphaned_grading_period_group
before_update :destroy_orphaned_grading_period_group
include StickySisFields
are_sis_sticky :name, :start_at, :end_at

View File

@ -1,5 +1,6 @@
class EpubExport < ActiveRecord::Base
include CC::Exporter::Epub::Exportable
include LocaleSelection
include Workflow
strong_params
@ -120,7 +121,9 @@ class EpubExport < ActiveRecord::Base
def convert_to_epub
begin
set_locale
file_paths = super
I18n.locale = :en
rescue => e
mark_as_failed
raise e
@ -160,4 +163,14 @@ class EpubExport < ActiveRecord::Base
def sort_by_content_type?
self.course.organize_epub_by_content_type
end
private
def set_locale
I18n.locale = infer_locale(
context: course,
user: user,
root_account: course.root_account
)
end
end

View File

@ -35,7 +35,8 @@ class FeatureFlag < ActiveRecord::Base
def unhides_feature?
return false unless Feature.definitions[feature].hidden?
return true if context.is_a?(Account) && context.site_admin?
Account.find(context.feature_flag_account_ids.last).lookup_feature_flag(feature, true).hidden?
parent_setting = Account.find(context.feature_flag_account_ids.last).lookup_feature_flag(feature, true)
parent_setting.nil? || parent_setting.hidden?
end
def enabled?

View File

@ -218,7 +218,7 @@ class GradingStandard < ActiveRecord::Base
def self.default_instance
gs = GradingStandard.new()
gs.data = default_grading_scheme
gs.title = "Default Grading Standard"
gs.title = "Default Grading Scheme"
gs
end

View File

@ -192,8 +192,9 @@ class SisBatch < ActiveRecord::Base
end
def fast_update_progress(val)
return true if val == self.progress
self.progress = val
SisBatch.where(:id => self).update_all(:progress=>val)
SisBatch.where(id: self).update_all(progress: val)
end
def importing?

View File

@ -227,11 +227,41 @@
width: 25px;
min-width: 25px;
}
// these are the classes that get applied to #right-side-wrapper to handle $.scrollSidebar
// NOTE: they used to get applied to body but were moved to #right side to not force a repaint
// of the entire page and be less jumpy going in and out display modes.
@mixin sidebar-logo {display: block;}
@if $use_new_styles {
.ic-sidebar-logo {
display: none;
margin-bottom: $ic-sp*2;
text-align: center;
}
.ic-sidebar-logo__image {
max-width: 180px;
max-height: 70px;
display: inline-block;
}
body:not(.course-menu-expanded) {
.ic-sidebar-logo {
@include breakpoint(desktop) {
@include sidebar-logo;
}
}
}
body.course-menu-expanded {
.ic-sidebar-logo {
@include breakpoint(desktop--nav-open) {
@include sidebar-logo;
}
}
}
}
// Legacy Styles
@if not $use_new_styles {
// These are the classes that get applied to #right-side-wrapper to handle $.scrollSidebar
// NOTE: they used to get applied to body but were moved to #right side to not force a repaint
// of the entire page and be less jumpy going in and out display modes.
.with-scrolling-right-side {
#right-side {
position: fixed;
@ -239,7 +269,6 @@
margin-top: 0;
}
}
#right-side-wrapper.with-sidebar-pinned-to-bottom {
position: absolute;
bottom: 0;

View File

@ -16,6 +16,105 @@ $ic-left-side-width: $ic-sp*15;
@else { background: $ic-border-dark; }
}
body:not(.ic-no-flex-layout):not(.embedded) .ic-app-main-content {
box-sizing: border-box;
flex: 1;
// Fix Firefox and IE Edge issues with contents breaking out of flex container
min-width: 1px;
}
.ic-app-main-content__primary {
box-sizing: border-box;
}
.ic-app-main-content__secondary {
box-sizing: border-box;
padding: $ic-sp*2;
position: relative; // note: this is also set for #right-side-wrapper in _#right-side.scss
// prevent safari bug where content disappears on scroll
-webkit-transform: translate3d(0, 0, 0);
}
/// Below are the shared styles for our content pieces. Because our layout
/// changes based on whether our course menu is open or shut
/// we needed to ensure we share the right styles with these sections, but
/// still enforce different breakpoints when needed
@mixin shared-main-content {display: flex;}
@mixin shared-primary {
flex: 1;
// Fix Firefox and IE Edge issues with contents breaking out of flex container
min-width: 1px;
}
@mixin shared-secondary {
flex: 0 0 $ic-sp*24;
padding-left: $ic-sp*2;
}
/// Layout when the course nav IS OPEN
body.course-menu-expanded {
&:not(.ic-no-flex-layout):not(.embedded) .ic-app-main-content {
@include breakpoint(desktop--nav-open) { @include shared-main-content; }
}
&:not(.ic-no-flex-layout):not(.embedded) .ic-app-main-content__primary {
@include breakpoint(desktop--nav-open) {
@include shared-primary;
}
}
.ic-app-main-content__secondary {
@include breakpoint(desktop--nav-open) {
@include shared-secondary;
}
}
}
/// Layout when the course nav IS CLOSED
body:not(.course-menu-expanded) {
&:not(.ic-no-flex-layout):not(.embedded) .ic-app-main-content {
@include breakpoint(desktop) { @include shared-main-content; }
}
&:not(.ic-no-flex-layout):not(.embedded) .ic-app-main-content__primary {
@include breakpoint(desktop) {
@include shared-primary;
}
}
.ic-app-main-content__secondary {
@include breakpoint(desktop) {
@include shared-secondary;
}
}
}
.ic-app-footer {
box-sizing: border-box;
padding: $ic-sp 0;
margin: 0 $ic-sp*2;
border-top: 1px solid $ic-border-light;
@include breakpoint(desktop) {
display: flex;
align-items: center;
}
body.modal & {
margin: 0;
padding: $ic-sp $ic-sp*2;
}
}
.ic-app-footer__links {
flex: 1;
display: flex;
a {
color: $ic-font-color--subdued;
margin-right: $ic-sp;
@include fontSize($ic-font-size--xsmall);
}
@include breakpoint(desktop) {
justify-content: flex-end;
a { margin-right: 0; margin-left: $ic-sp; }
}
}
.ic-app {
box-sizing: border-box;
min-height: 100vh;
@ -103,71 +202,6 @@ $ic-left-side-width: $ic-sp*15;
}
}
.ic-app-main-content {
body:not(.ic-no-flex-layout):not(.embedded) & {
box-sizing: border-box;
flex: 1;
@include breakpoint(desktop) { display: flex; }
// Fix Firefox and IE Edge issues with contents breaking out of flex container
min-width: 1px;
}
}
.ic-app-main-content__primary {
box-sizing: border-box;
@include breakpoint(desktop) {
body:not(.ic-no-flex-layout):not(.embedded) & {
flex: 1;
// Fix Firefox and IE Edge issues with contents breaking out of flex container
min-width: 1px;
}
}
}
.ic-app-main-content__secondary {
box-sizing: border-box;
padding: $ic-sp*2;
@include breakpoint(desktop) {
flex: 0 0 $ic-sp*24;
padding-left: $ic-sp*2;
}
position: relative; // note: this is also set for #right-side-wrapper in _#right-side.scss
// prevent safari bug where content disappears on scroll
-webkit-transform: translate3d(0, 0, 0);
}
.ic-app-footer {
box-sizing: border-box;
padding: $ic-sp 0;
margin: 0 $ic-sp*2;
border-top: 1px solid $ic-border-light;
@include breakpoint(desktop) {
display: flex;
align-items: center;
}
body.modal & {
margin: 0;
padding: $ic-sp $ic-sp*2;
}
}
.ic-app-footer__links {
flex: 1;
display: flex;
a {
color: $ic-font-color--subdued;
margin-right: $ic-sp;
@include fontSize($ic-font-size--xsmall);
}
@include breakpoint(desktop) {
justify-content: flex-end;
a { margin-right: 0; margin-left: $ic-sp; }
}
}
.ic-app-nav-toggle-and-crumbs {
display: flex;
align-items: center;

View File

@ -256,7 +256,23 @@ iframe.tool_launch {
height: 100%;
border: none;
}
// implemented to make new profile page use flex for layout //
.ic-Layout {
display: flex;
padding: $ic-sp;
box-sizing: border-box;
width: 100%;
}
.ic-Layout__Primary {
flex: 2;
@include breakpoint(desktop) {
flex: 3;
}
}
.ic-Layout__Secondary {
flex: 1;
text-align: right;
}
#skip_navigation_link {
@include accessibility-prompt;
position: absolute;

View File

@ -9,4 +9,7 @@
@else if $breakpoint == desktop {
@media only screen and (min-width: 992px) { @content; }
}
@else if $breakpoint == desktop--nav-open {
@media only screen and (min-width: 1140px) { @content; }
}
}

View File

@ -12,6 +12,12 @@
display: none !important;
}
}
.profile .image-block {
flex-direction: column;
@include breakpoint(desktop) {
flex-direction: row;
}
}
.profile-avatar-wrapper {
margin-right: 20px !important;
@ -83,9 +89,7 @@
#edit_links_table {
width: 100%;
input {
width: 95%;
}
td {
text-align: center;
}
@ -99,21 +103,31 @@
overflow: hidden;
}
#content {
.h1, .h2 {
line-height: 21px;
}
.profileContent__Block {
display: flex;
flex-direction: column;
flex: 1;
}
#content h1 {
.profileDetails {
margin-top: 0;
}
.profileEnrollment__Items {
padding: $ic-sp/2 0;
}
.profileLink {
margin: 0;
}
#content h2 {
margin: 1em 0 0.5em 0;
color: $gray;
.profileLink__Item {
list-style: none;
line-height: 2.0;
& a {
padding-left: $ic-sp/2;
}
}
.profileHeader {
padding: $ic-sp 0 0 0;
line-height: 1.25;
}
.stats {
text-align: left;
width: 100%;

View File

@ -4,19 +4,28 @@
width: 100%;
}
tr.login > th, tr.login > td {
padding-top: 5px;
padding-top: 0;
padding-bottom: 5px;
border-bottom: 1px solid #eee;
vertical-align: top;
&.sso-icon { vertical-align: middle; }
}
.details {
font-size: 0.8em;
padding-left: 20px;
.account_name {
line-height: 3.0;
}
.account {
font-size: 0.8em;
padding-left: 10px;
.login_details {
padding: 0;
}
.login_details td:first-child {
font-weight: 500;
}
.login_details:last-child {
& td {
border-bottom: none;
}
}
.login_details_link {
font-style: italic;
}
.links {
white-space: nowrap;

View File

@ -100,7 +100,8 @@
.user_content, .mceContentBody {
position: relative;
min-height: 5px;
// firefox max-width images break the parent container
max-width: 100%;
// firefox max-width images break the parent container
@-moz-document url-prefix() {
overflow-x: hidden;
}
@ -128,6 +129,7 @@
border: 0;
padding: 0;
margin: 0;
max-width: 100%;
}
.reminder, .reminder-content {

View File

@ -4,7 +4,7 @@
<br/>
### tl;dr
- Actions is the header bar should exist on the right
- Actions is the header bar should exist on the right
- Cog menus should always be the most right
- Many actions should be grouped by related function, IE (edit/delete content) and (preview/publish content)
- Left side should be used for filtering and searching content

View File

@ -6,6 +6,11 @@
line-height: 17px;
cursor: pointer;
input {
width: 16px;
height: 20px;
}
&.enabled {
font-weight: bold;
@if $use_high_contrast { color: darken($ic-color-success, 4%); }

View File

@ -172,6 +172,9 @@ body:not(.with-left-side) & .ic-app-nav-toggle-and-crumbs--files {
position: relative;
margin: 10px;
flex: 3;
// long file names cause this container, of all things, to expand unreasonably even after they get elided. Work
// around that for the moment with this.
max-width: 75%;
display: flex;
flex-direction: column;

View File

@ -1,36 +1,48 @@
<div class="rs-margin-lr <% unless use_new_styles? %>rs-margin-top<% end %>">
<% if @context.is_a?(Course) %>
<div id="people-options" class="al-dropdown__container" style="position: relative;">
<button type="button" class="al-trigger Button">
<i class="icon-settings"></i>
<i class="icon-mini-arrow-down"></i>
<span class="screenreader-only">More Options</span>
</button>
<ul class="al-options" role="menu" tabindex="0" aria-hidden="true">
<% if @context.is_a?(Course) %>
<% if can_do(@context, @current_user, :read_roster) %>
<li role="presentation">
<%= sidebar_button context_url(@context, :context_groups_url),
t('View User Groups'),
'group' %>
</li>
<% end %>
<% if can_do(@context, @current_user, :manage_students && @context.enable_user_notes) %>
<li role="presentation">
<%= sidebar_button course_user_notes_path(@context),
t('View Faculty Journals') %>
</li>
<% end %>
<% if can_do(@context, @current_user, :manage_admin_users, :manage_students, :read_prior_roster) %>
<li role="presentation">
<%= sidebar_button course_prior_users_path(@context),
t('View Prior Enrollments'),
'clock' %>
</li>
<% end %>
<% if @context.user_is_instructor?(@current_user) && can_do(@context, @current_user, :read_reports) %>
<li role="presentation">
<%= sidebar_button user_course_teacher_activity_url(@current_user, @context),
t('Student Interactions Report'),
'user' %>
</li>
<% end %>
<% end %>
<% if can_do(@context, @current_user, :read_roster) %>
<%= sidebar_button context_url(@context, :context_groups_url),
t('links.view_user_groups', 'View User Groups'),
'group' %>
<li role="presentation">
<%= sidebar_button context_url(@context, :context_user_services_url),
t('links.view_services', 'View Registered Services'),
'link' %>
</li>
<% end %>
<% if can_do(@context, @current_user, :manage_students && @context.enable_user_notes) %>
<%= sidebar_button course_user_notes_path(@context),
t('links.view_faculty_journals', 'View Faculty Journals') %>
<% end %>
<% if can_do(@context, @current_user, :manage_admin_users, :manage_students, :read_prior_roster) %>
<%= sidebar_button course_prior_users_path(@context),
t('links.view_prior_enrollments', 'View Prior Enrollments'),
'clock' %>
<% end %>
<% end %>
<% if can_do(@context, @current_user, :read_roster) %>
<%= sidebar_button context_url(@context, :context_user_services_url),
t('links.view_services', 'View Registered Services'),
'link' %>
<% end %>
<% if @context.is_a?(Course) %>
<% if @context.user_is_instructor?(@current_user) && can_do(@context, @current_user, :read_reports) %>
<%= sidebar_button user_course_teacher_activity_url(@current_user, @context),
t('Student Interactions Report'),
'user' %>
<% end %>
<% end %>
</ul>
</div>

View File

@ -48,59 +48,67 @@
<div class="more_user_information">
<% if @context.is_a?(Course) %>
<fieldset>
<legend><%= t('legends.memberships', %{Membership(s)}) %></legend>
<table>
<legend>
<h4 class="profileHeader">
<%= t('legends.memberships', %{Membership(s)}) %>
</h4>
</legend>
<table class="ic-Table--condensed">
<% @enrollments.sort_by(&:id).each do |enrollment| %>
<tr class="enrollment">
<td style="vertical-align: top; padding: 5px 50px 5px 5px;">
<b><a href="<%= context_url(@context, :context_section_url, enrollment.course_section_id) rescue "#" %>"><%= enrollment.try_rescue(:course_section).try_rescue(:display_name) || enrollment.short_name %></a></b>
<div style="font-size: 0.8em; padding-left: 20px;"><%= t 'enrolled_as', "Enrolled as a %{enrollment_type}", :enrollment_type => enrollment.readable_type %></div>
<div style="font-size: 0.8em; padding-left: 20px;">created <%= datetime_string(enrollment.created_at) %></div>
<% if enrollment.is_a?(ObserverEnrollment) %>
<div style="font-size: 0.8em; padding-left: 20px; <%= hidden unless enrollment.associated_user %>" class="associated_user" >
<%= t 'enrollment_linked_to', "linked to *%{linked_user}*",
:linked_user => context_user_name(@context, enrollment.associated_user),
:wrapper => '<span class="associated_user_name">\1</span>' %>
</div>
<% end %>
<div style="font-size: 0.8em; padding-left: 20px; <%= hidden unless enrollment.completed? %>" class="completed_at_holder"><%= t 'completed_enrollment', "completed *%{completed_at}*", :completed_at => datetime_string(enrollment.completed_at), :wrapper => '<span class="completed_at">\1</span>' %></div>
<tr id="enrollment">
<td scope="row" style="width: 30%;">
<a href="<%= context_url(@context, :context_section_url, enrollment.course_section_id) rescue "#" %>"><%= enrollment.try_rescue(:course_section).try_rescue(:display_name) || enrollment.short_name %></a>
</td>
<td style="width: 30%;">
<%= t 'enrolled_as', "Enrolled as a %{enrollment_type}", :enrollment_type => enrollment.readable_type %> | created <%= datetime_string(enrollment.created_at) %>
</td>
<% if enrollment.is_a?(ObserverEnrollment) %>
<td style="<%= hidden unless enrollment.associated_user %>" class="associated_user" >
<%= t 'enrollment_linked_to', "linked to *%{linked_user}*",
:linked_user => context_user_name(@context, enrollment.associated_user),
:wrapper => '<span class="associated_user_name">\1</span>' %>
</td>
<% end %>
<td style="width: 20%; <%= hidden unless enrollment.completed? %>">
<p class="completed_at_holder"><%= t 'completed_enrollment', "completed *%{completed_at}*", :completed_at => datetime_string(enrollment.completed_at), :wrapper => '<span class="completed_at">\1</span>' %></p>
</td>
<td style="width: 10%;">
<% if enrollment.admin? ? (can_manage_admins && enrollment.user_id != @current_user.id) : can_manage_students %>
<td style="vertical-align: top; padding: 5px; font-size: 0.8em;">
<% unless @context.completed? %>
<div class="conclude_enrollment_link_holder" style="margin-bottom: 5px; <%= hidden if enrollment.completed? %>">
<a class="conclude_enrollment_link" href="<%= context_url(@context, :controller => :courses, :action => :conclude_user, :id => enrollment.id) %>"><%= t('links.conclude_enrollment', %{Conclude this Enrollment}) %></a>
</div>
<div class="unconclude_enrollment_link_holder" style="margin-bottom: 5px; <%= hidden unless enrollment.explicitly_completed? || enrollment.inactive? %>">
<a class="unconclude_enrollment_link" href="<%= context_url(@context, :controller => :courses, :action => :unconclude_user, :id => enrollment.id) %>"><%= t('links.restore_enrollment', %{Restore this Enrollment}) %></a>
</div>
<% end %>
<div><% if enrollment.defined_by_sis? %>
<% unless @context.completed? %>
<p class="conclude_enrollment_link_holder" style="<%= hidden if enrollment.completed? %>">
<a class="conclude_enrollment_link" href="<%= context_url(@context, :controller => :courses, :action => :conclude_user, :id => enrollment.id) %>"><%= t('links.conclude_enrollment', %{Conclude}) %></a>
</p>
<p class="unconclude_enrollment_link_holder" style="<%= hidden unless enrollment.explicitly_completed? || enrollment.inactive? %>">
<a class="unconclude_enrollment_link" href="<%= context_url(@context, :controller => :courses, :action => :unconclude_user, :id => enrollment.id) %>"><%= t('links.restore_enrollment', %{Restore}) %></a>
</p>
<% end %>
</td>
<td style="width: 10%;">
<p>
<% if enrollment.defined_by_sis? %>
<a href="#" title="<%= t('links.title.enrollment_sis_defined', %{This enrollment was defined by the university, and can't be deleted}) %>"><%= t('links.cant_delete', %{Can't Delete}) %></a>
<% else %>
<a class="delete_enrollment_link" href="<%= context_url(@context, :context_unenroll_url, enrollment.id) %>"><%= t('links.delete_enrollment', %{Delete this Enrollment}) %></a>
<a class="delete_enrollment_link" href="<%= context_url(@context, :context_unenroll_url, enrollment.id) %>"><%= t('links.delete_enrollment', %{Delete}) %></a>
<% end %>
</div>
</td>
</p>
</td>
<% end %>
</tr>
<% end %>
<% if @context.is_a?(Course) && can_do(@context, @current_user, :manage_admin_users) %>
<tr>
<td style="border-top: 1px solid #eee; padding-top: 5px; vertical-align: top; font-weight: bold;"><%= before_label('user_privileges', %{Privileges}) %></td>
<td style="border-top: 1px solid #eee; padding-top: 5px;">
<div class="elevate_enrollment_link_holder" style="<%= hidden if @enrollments.any?{|e| !e.limit_privileges_to_course_section } %>">
<%= t('user_only_view_section', %{this user can only view students in their assigned course section(s)}) %>
<div style="margin-left: 10px; font-size: 0.8em;">
<a href="<%= context_url(@context, :context_limit_user_grading_url, @user.id) %>" class="elevate_enrollment_link"><%= t('links.user_view_all_sections', %{let this user see all course users}) %></a>
</div>
</div>
<div class="restrict_enrollment_link_holder" style="<%= hidden unless @enrollments.any?{|e| !e.limit_privileges_to_course_section } %>">
<%= t('user_view_all_sections', %{this user can view students in any course section}) %>
<div style="margin-left: 10px; font-size: 0.8em;">
<a href="<%= context_url(@context, :context_limit_user_grading_url, @user.id) %>" class="restrict_enrollment_link"><%= t('links.user_only_view_section', %{limit this user to only see fellow section users}) %></a>
</div>
</div>
<tr id="priveleges">
<td scope="row">
<%= before_label('user_privileges', %{Privileges}) %>
</td>
<td colspan="2">
<p class="elevate_enrollment_link_holder" style="<%= hidden if @enrollments.any?{|e| !e.limit_privileges_to_course_section } %>">
<%= t('user_only_view_section', %{this user can only view students in their assigned course section(s)}) %><br/>
<a href="<%= context_url(@context, :context_limit_user_grading_url, @user.id) %>" class="elevate_enrollment_link"><%= t('links.user_view_all_sections', %{let this user see all course users}) %></a>
</p>
<p class="restrict_enrollment_link_holder" style="<%= hidden unless @enrollments.any?{|e| !e.limit_privileges_to_course_section } %>">
<%= t('user_view_all_sections', %{this user can view students in any course section}) %><br/>
<a href="<%= context_url(@context, :context_limit_user_grading_url, @user.id) %>" class="restrict_enrollment_link"><%= t('links.user_only_view_section', %{limit this user to only see fellow section users}) %></a>
</p>
</td>
</tr>
<% end %>

View File

@ -6,12 +6,19 @@
content_for :page_title, join_title(translated_title, @context.name)
%>
<h1 class='screenreader-only'><%= t('#titles.people', 'People') %></h1>
<% content_for :right_side, render(:partial => 'context/roster_right_side') %>
<% css_bundle :roster %>
<div class="ic-Action-header">
<div class="ic-Action-header__Primary">
<h1 class="screenreader-only"><%= t('#titles.people', 'People') %></h1>
</div>
<div class="ic-Action-header__Secondary">
<%= render :partial => 'context/roster_right_side' %>
</div>
</div>
<% if @context.is_a?(Course) %>
<% js_bundle :roster %>
<% js_env :canManageCourse => can_do(@context, @current_user, :manage) %>

View File

@ -89,79 +89,81 @@
<% if !@context.is_a?(Group) && (can_manage_students || can_manage_admins) %>
<%= render :partial => 'users/name' %>
<a href="#" class="more_user_information_link"><%= t('links.more_user_details', %{more user details...}) %></a>
<div class="more_user_information" style="display: none;">
<% if @context.is_a?(Course) %>
<fieldset>
<legend><%= t('legends.memberships', %{Membership(s)}) %></legend>
<table>
<% @enrollments.sort_by(&:id).each do |enrollment| %>
<tr class="enrollment">
<td style="vertical-align: top; padding: 5px 50px 5px 5px;">
<b><a href="<%= context_url(@context, :context_section_url, enrollment.course_section_id) rescue "#" %>"><%= enrollment.try_rescue(:course_section).try_rescue(:display_name) || enrollment.short_name %></a></b>
<div style="font-size: 0.8em; padding-left: 20px;"><%= t 'enrolled_as', "Enrolled as a %{enrollment_type}", :enrollment_type => enrollment.readable_type %></div>
<div style="font-size: 0.8em; padding-left: 20px;">created <%= datetime_string(enrollment.created_at) %></div>
<% if enrollment.is_a?(ObserverEnrollment) %>
<div style="font-size: 0.8em; padding-left: 20px; <%= hidden unless enrollment.associated_user %>" class="associated_user" >
<%= t 'enrollment_linked_to', "linked to *%{linked_user}*",
:linked_user => context_user_name(@context, enrollment.associated_user),
:wrapper => '<span class="associated_user_name">\1</span>' %>
</div>
<% end %>
<div style="font-size: 0.8em; padding-left: 20px; <%= hidden unless enrollment.completed? || enrollment.inactive? %>" class="completed_at_holder">
<% if enrollment.inactive? %>
<%= t 'inactive' %>
<% elsif enrollment.completed_at %>
<%= t 'completed_enrollment', "completed *%{completed_at}*", :completed_at => datetime_string(enrollment.completed_at), :wrapper => '<span class="completed_at">\1</span>' %>
<% else %>
<%= t 'completed' %>
<% end %>
</div>
</td>
<% if enrollment.admin? ? (can_manage_admins && enrollment.user_id != @current_user.id) : can_manage_students %>
<td style="vertical-align: top; padding: 5px; font-size: 0.8em;">
<% unless @context.completed? %>
<div class="conclude_enrollment_link_holder" style="margin-bottom: 5px; <%= hidden if enrollment.completed? %>">
<a class="conclude_enrollment_link" href="<%= context_url(@context, :controller => :courses, :action => :conclude_user, :id => enrollment.id) %>"><%= t('links.conclude_enrollment', %{Conclude this Enrollment}) %></a>
</div>
<div class="unconclude_enrollment_link_holder" style="margin-bottom: 5px; <%= hidden unless enrollment.explicitly_completed? || enrollment.inactive? %>">
<a class="unconclude_enrollment_link" href="<%= context_url(@context, :controller => :courses, :action => :unconclude_user, :id => enrollment.id) %>"><%= t('links.restore_enrollment', %{Restore this Enrollment}) %></a>
<div class="more_user_information" style="display: none;">
<% if @context.is_a?(Course) %>
<fieldset>
<legend><h3><%= t('legends.memberships', %{Membership(s)}) %></h3></legend>
<table class="ic-Table">
<% @enrollments.sort_by(&:id).each do |enrollment| %>
<tr class="enrollment">
<td>
<b><a href="<%= context_url(@context, :context_section_url, enrollment.course_section_id) rescue "#" %>"><%= enrollment.try_rescue(:course_section).try_rescue(:display_name) || enrollment.short_name %></a></b>
<div><%= t 'enrolled_as', "Enrolled as a %{enrollment_type}", :enrollment_type => enrollment.readable_type %></div>
<div>created <%= datetime_string(enrollment.created_at) %></div>
<% if enrollment.is_a?(ObserverEnrollment) %>
<div style="font-size: 0.8em; padding-left: 20px; <%= hidden unless enrollment.associated_user %>" class="associated_user" >
<%= t 'enrollment_linked_to', "linked to *%{linked_user}*",
:linked_user => context_user_name(@context, enrollment.associated_user),
:wrapper => '<span class="associated_user_name">\1</span>' %>
</div>
<% end %>
<div><% if enrollment.defined_by_sis? %>
<a href="#" title="<%= t('links.title.enrollment_sis_defined', %{This enrollment was defined by the university, and can't be deleted}) %>"><%= t('links.cant_delete', %{Can't Delete}) %></a>
<% else %>
<a class="delete_enrollment_link" href="<%= context_url(@context, :context_unenroll_url, enrollment.id) %>"><%= t('links.delete_enrollment', %{Delete this Enrollment}) %></a>
<% end %>
<div style="font-size: 0.8em; padding-left: 20px; <%= hidden unless enrollment.completed? || enrollment.inactive? %>" class="completed_at_holder">
<% if enrollment.inactive? %>
<%= t 'inactive' %>
<% elsif enrollment.completed_at %>
<%= t 'completed_enrollment', "completed *%{completed_at}*", :completed_at => datetime_string(enrollment.completed_at), :wrapper => '<span class="completed_at">\1</span>' %>
<% else %>
<%= t 'completed' %>
<% end %>
</div>
</td>
<% end %>
</tr>
<% end %>
<% if @context.is_a?(Course) && can_do(@context, @current_user, :manage_admin_users) %>
<tr>
<td style="border-top: 1px solid #eee; padding-top: 5px; vertical-align: top; font-weight: bold;"><%= before_label('user_privileges', %{Privileges}) %></td>
<td style="border-top: 1px solid #eee; padding-top: 5px;">
<div class="elevate_enrollment_link_holder" style="<%= hidden if @enrollments.any?{|e| !e.limit_privileges_to_course_section } %>">
<%= t('user_only_view_section', %{this user can only view students in their assigned course section(s)}) %>
<div style="margin-left: 10px; font-size: 0.8em;">
<a href="<%= context_url(@context, :context_limit_user_grading_url, @user.id) %>" class="elevate_enrollment_link"><%= t('links.user_view_all_sections', %{let this user see all course users}) %></a>
<% if enrollment.admin? ? (can_manage_admins && enrollment.user_id != @current_user.id) : can_manage_students %>
<td>
<% unless @context.completed? %>
<div class="conclude_enrollment_link_holder" style="margin-bottom: 5px; <%= hidden if enrollment.completed? %>">
<a class="conclude_enrollment_link" href="<%= context_url(@context, :controller => :courses, :action => :conclude_user, :id => enrollment.id) %>"><%= t('links.conclude_enrollment', %{Conclude this Enrollment}) %></a>
</div>
<div class="unconclude_enrollment_link_holder" style="margin-bottom: 5px; <%= hidden unless enrollment.explicitly_completed? || enrollment.inactive? %>">
<a class="unconclude_enrollment_link" href="<%= context_url(@context, :controller => :courses, :action => :unconclude_user, :id => enrollment.id) %>"><%= t('links.restore_enrollment', %{Restore this Enrollment}) %></a>
</div>
<% end %>
<div><% if enrollment.defined_by_sis? %>
<a href="#" title="<%= t('links.title.enrollment_sis_defined', %{This enrollment was defined by the university, and can't be deleted}) %>"><%= t('links.cant_delete', %{Can't Delete}) %></a>
<% else %>
<a class="delete_enrollment_link" href="<%= context_url(@context, :context_unenroll_url, enrollment.id) %>"><%= t('links.delete_enrollment', %{Delete this Enrollment}) %></a>
<% end %>
</div>
</td>
<% end %>
</tr>
<% end %>
<% if @context.is_a?(Course) && can_do(@context, @current_user, :manage_admin_users) %>
<tr>
<td>
<%= before_label('user_privileges', %{Privileges}) %>
</td>
<td>
<div class="elevate_enrollment_link_holder" style="<%= hidden if @enrollments.any?{|e| !e.limit_privileges_to_course_section } %>">
<%= t('user_only_view_section', %{this user can only view students in their assigned course section(s)}) %>
<div style="margin-left: 10px; font-size: 0.8em;">
<a href="<%= context_url(@context, :context_limit_user_grading_url, @user.id) %>" class="elevate_enrollment_link"><%= t('links.user_view_all_sections', %{let this user see all course users}) %></a>
</div>
</div>
</div>
<div class="restrict_enrollment_link_holder" style="<%= hidden unless @enrollments.any?{|e| !e.limit_privileges_to_course_section } %>">
<%= t('user_view_all_sections', %{this user can view students in any course section}) %>
<div style="margin-left: 10px; font-size: 0.8em;">
<a href="<%= context_url(@context, :context_limit_user_grading_url, @user.id) %>" class="restrict_enrollment_link"><%= t('links.user_only_view_section', %{limit this user to only see fellow section users}) %></a>
<div class="restrict_enrollment_link_holder" style="<%= hidden unless @enrollments.any?{|e| !e.limit_privileges_to_course_section } %>">
<%= t('user_view_all_sections', %{this user can view students in any course section}) %>
<div style="margin-left: 10px; font-size: 0.8em;">
<a href="<%= context_url(@context, :context_limit_user_grading_url, @user.id) %>" class="restrict_enrollment_link"><%= t('links.user_only_view_section', %{limit this user to only see fellow section users}) %></a>
</div>
</div>
</div>
</td>
</tr>
<% end %>
</table>
</fieldset>
<%= render :partial => 'courses/link_enrollment' %>
<% end %>
<%= render :partial => 'users/logins' %>
</div>
</td>
</tr>
<% end %>
</table>
</fieldset>
<%= render :partial => 'courses/link_enrollment' %>
<% end %>
<%= render :partial => 'users/logins' %>
</div>
<div style="margin-bottom: 10px;">&nbsp;</div>
<% elsif service_enabled?(:avatars) %>
<div style="margin-bottom: 20px;">

View File

@ -2,7 +2,7 @@
<div id="link_student_dialog" style="display: none;">
<a href="<%= context_url(@context, :context_students_url) %>" class="student_url" style="display: none;">&nbsp;</a>
<%= form_tag context_url(@context, :context_link_enrollment_url), {:id => "link_student_dialog_form"} do %>
<input type="hidden" name="enrollment_id" class="enrollment_id"/>
<input type="hidden" name="enrollment_id" class="enrollment_id ic-Input"/>
<%= mt 'details', %{When an observer is linked to a student, they have access to that student's grades and course interactions. *Right now this observer is linked to the student, %{student}.*
To link the course observer %{user} to a student, select the student's name from the list below.},
@ -11,7 +11,7 @@ To link the course observer %{user} to a student, select the student's name from
:user => '<b class="short_name">&nbsp;</b>'.html_safe %>
<p class="loading_message"><%= t('loading', %{Loading Students...}) %></p>
<p class="students_link" style="display: none;">
<label for="student_enrollment_link_option"><%= before_label('student', %{Student}) %></label>
<label for="student_enrollment_link_option" class="ic-Label"><%= before_label('student', %{Student}) %></label>
<select name="student_id" class="student_options" id="student_enrollment_link_option">
<option value="none" class="blank">[ <%= t('select_student', %{Select Student}) %> ]</option>
</select>

View File

@ -0,0 +1,4 @@
<span class="post-to-sis-status">
<label class="screenreader-only" aria-live="polite"></label>
<input type='image' class='icon-post-to-sis' data-tooltip/>
</span>

View File

@ -56,19 +56,7 @@
{{#if canManage}}
<div class="ig-admin">
{{#if postToSISEnabled}}
{{#if postToSIS}}
<span class="post-to-sis-status enabled">
<img class='icon-post-to-sis accessible_label' src='/images/svg-icons/svg_icon_post_to_sis_active.svg' aria-label='Post grades to SIS enabled' tabindex='0' role='button' width=16 height=20 title='{{#t}}Post grade to SIS enabled. Click to toggle.{{/t}}' data-tooltip />
<span class="screenreader-only accessible_label">{{#t}}The grade for this assignment will sync to the student information system.{{/t}}</span>
</span>
{{else}}
<span class="post-to-sis-status disabled">
<img class='icon-post-to-sis accessible_label' src='/images/svg-icons/svg_icon_post_to_sis.svg' aria-label='Post grades to SIS disabled' tabindex='0' role='button' width=16 height=20 title='{{#t}}Post grade to SIS disabled. Click to toggle.{{/t}}' data-tooltip />
<span class="screenreader-only accessible_label">{{#t}}The grade for this assignment will not sync to the student information system.{{/t}}</span>
</span>
{{/if}}
{{/if}}
<span class="sis-button" data-view="sis-button"></span>
<span class="publish-icon" data-view="publish-icon"></span>

View File

@ -7,7 +7,7 @@
</a>
</div>
{{/if}}
<div class="roster-tab tab-panel ui-tabs-panel form-inline" style="min-height: 800px;">
<div id="tab-0" class="roster-tab tab-panel ui-tabs-panel form-inline" style="min-height: 800px;">
<input
type="text"
name="search_term"

View File

@ -1,5 +1,5 @@
<li class="static ui-state-default ui-corner-top ui-tabs-active ui-state-active" role="tab" >
<a href="#" class="ui-tabs-anchor" role="presentation" tabindex="-1">{{#t 'everyone_tab'}}Everyone{{/t}}</a>
<a href="#tab-0" class="ui-tabs-anchor" role="presentation" tabindex="-1">{{#t 'everyone_tab'}}Everyone{{/t}}</a>
</li>
{{#each collection}}
<li role="tab" class="ui-state-default ui-corner-top" >

View File

@ -1,6 +1,6 @@
<tr>
<td><input aria-label="{{t "Link title" }}" type="text" maxlength="255" name="link_titles[]" value="{{title}}"></td>
<td><input aria-label="{{t "Link title" }}" type="text" class="ic-Input" maxlength="255" name="link_titles[]" value="{{title}}"></td>
<td>→</td>
<td><input aria-label="{{t "Link Url" }}" type="text" name="link_urls[]" value="{{url}}"></td>
<td><input aria-label="{{t "Link Url" }}" type="text" class="ic-Input" name="link_urls[]" value="{{url}}"></td>
<td><a href="#" class="remove_link_row" data-event="removeLinkRow"><span class="screenreader-only">{{t "Remove" }}</span><i class="icon-end"></i></a></td>
</tr>

View File

@ -24,19 +24,7 @@
{{#if can_update}}
<div class="ig-admin">
{{#if post_to_sis_enabled}}
{{#if post_to_sis}}
<span class="post-to-sis-status enabled">
<i class="icon-post-to-sis" title='{{#t}}Post grade to SIS enabled. Click to toggle.{{/t}}' data-tooltip></i>
<span class="screenreader-only">{{#t}}The grade for this assignment will sync to the student information system. Click here to toggle this setting.{{/t}}</span>
</span>
{{else}}
<span class="post-to-sis-status disabled">
<i class="icon-post-to-sis" title='{{#t}}Post grade to SIS disabled. Click to toggle.{{/t}}' data-tooltip></i>
<span class="screenreader-only">{{#t}}The grade for this assignment will not sync to the student information system. Click here to toggle this setting.{{/t}}</span>
</span>
{{/if}}
{{/if}}
<span class="sis-button" data-view="sis-button"></span>
<span data-view="publish-icon" class="publish-icon"></span>
<div class="inline-block">

View File

@ -1,20 +1,31 @@
<% content_for :page_title, @user_data[:short_name] %>
<%= render 'shared/profile' %>
<div class="ic-Layout">
<div class="ic-Layout__Primary">
<%= render 'shared/profile' %>
</div>
<% content_for :right_side do %>
<div class="rs-margin-all">
<% if @user_data[:can_edit] %>
<button data-event="editProfile" class="hide-if-editing btn button-sidebar-wide"><i class="icon-edit"></i> <%= t('edit_profile', 'Edit Profile') %></button>
<button data-event="cancelEditProfile" class="show-if-editing btn button-sidebar-wide"><i class="icon-edit"></i> <%= t('cancel_editing', 'Cancel Editing') %></button>
<% end %>
<% if can_do(@domain_root_account, @current_user, :manage) %>
<h1 class="h2 right-side-h2-border"><%= t :administration, 'Administration' %></h1>
<div><a href="<%= user_path(@user.id) %>"><%= t('links.user_account_details', %{Account Details}) %></a></div>
<% if @user != @current_user %>
<div><a href="<%= user_profile_url(@user, :become_user_id => @user) %>"> <%= t('become', 'Become') %></a></div>
<% end %>
<div class="ic-Layout__Secondary">
<% if @user_data[:can_edit] && !can_do(@domain_root_account, @current_user, :manage) %>
<button data-event="editProfile" class="hide-if-editing Button"><i class="icon-edit"></i> <%= t('edit_profile', 'Edit Profile') %></button>
<button data-event="cancelEditProfile" class="show-if-editing Button"><i class="icon-edit"></i> <%= t('cancel_editing', 'Cancel Editing') %></button>
<% elsif @user_data[:can_edit] && can_do(@domain_root_account, @current_user, :manage) %>
<div class="al-dropdown__container">
<a class="al-trigger btn" role="button" href="#" id="profileDropdown">
<i class="icon-more" role="presentation"></i>
<span class="screenreader-only">More</span>
</a>
<ul aria-labeledby="profileDropdown" class="al-options" role="menu" tabindex="0" aria-hidden="true" aria-expanded="false" >
<li class="hide-if-editing"><a data-event="editProfile" role="menuitem"><%= t('edit_profile', 'Edit Profile') %></a></li>
<li class="show-if-editing"><a data-event="cancelEditProfile" role="menuitem"><%= t('cancel_editing', 'Cancel Editing') %></a></li>
<li><a href="<%= user_path(@user.id) %>"role="menuitem"><%= t('links.user_account_details', %{Account Details}) %></a></li>
<% if @user != @current_user %>
<li><a href="<%= user_profile_url(@user, :become_user_id => @user) %>"role="menuitem"> <%= t('masquerade', 'Masquerade') %></a></li>
<% end %>
</ul>
</div>
<% end %>
</div>
<% end %>
</div>

View File

@ -53,7 +53,7 @@
<table style="width: 100%; margin-bottom: 20px;" class="grading_standard_data">
<caption class="screenreader-only">
<%= t("Current grading standard for this assignment") %>
<%= t("Current grading scheme for this assignment") %>
</caption>
<thead>
<tr>

View File

@ -5,7 +5,7 @@
js_env PROFILE: @user_data if @user_data[:can_edit]
js_env(folder_id: @user.profile_pics_folder.id) if @user == @current_user
%>
<%= form_tag update_profile_profile_path, { :method => :put, :id => :edit_profile_form, :class => "bootstrap-form form-vertical" } do %>
<%= form_tag update_profile_profile_path, { :method => :put, :id => :edit_profile_form, :class => "ic-Form-control" } do %>
<div class="image-block">
<div class="image-block-image profile-avatar-wrapper">
<% if @user_data[:can_edit] %>
@ -17,137 +17,144 @@
<%= avatar(@user_data[:id], size: 128, url: nil) %>
<% end %>
</div>
<div class="image-block-content row-fluid">
<div class="profileContent__Block">
<% if @user_data[:can_edit_name] %>
<h1 class="h1">
<span class="hide-if-editing"><%= @user_data[:short_name] %></span>
</h1>
<label class="show-if-editing"><%= t('name', 'Name') %>: <br><input type="text" name="user[short_name]" value="<%= @user_data[:short_name] %>" required></label>
<p>
<h2 class="hide-if-editing"><%= @user_data[:short_name] %></h2>
<label class="show-if-editing ic-Label"><%= t('name', 'Name') %>:
<input class="ic-Input" type="text" name="user[short_name]" value="<%= @user_data[:short_name] %>" required>
</label>
<p class="profileDetails">
<span class="hide-if-editing"><%= @user_data[:title] %></span>
<label class="show-if-editing"><%= t('title', 'Title') %>: <br><input type="text" name="user_profile[title]" value="<%= @user_data[:title] %>"></label>
<label class="show-if-editing ic-Label"><%= t('title', 'Title') %>:
<input class="ic-Input" type="text" name="user_profile[title]" value="<%= @user_data[:title] %>">
</label>
</p>
<% else %>
<h1 class="h1">
<span><%= @user_data[:short_name] %></span>
</h1>
<p>
<span><%= @user_data[:title] %></span>
</p>
<h2><%= @user_data[:short_name] %></h2>
<p><%= @user_data[:title] %></p>
<% end %>
<div class="show-if-editing edit-contact-methods">
<h2 class="h5 border border-b"><%= t('#profile.ways_to_contact_me', "Ways to contact me") %></h2>
<% if @user_data[:user_services].present? %>
<div class="row-fluid">
<div class="span6">
<ul class="social-links">
<h3 class="profileHeader"><%= t('#profile.ways_to_contact_me', "Contact") %></h3>
<% if @user_data[:user_services].present? %>
<ul class="social-links">
<li>
<label for="social_message" class="social message ic-Label" title="<%= t :message_title, 'Message' %>" data-tooltip><%= t :message_me, 'message me in Canvas' %></label>
</li>
<% @user_data[:user_services].each do |s| %>
<li>
<label for="social_message" class="social message" title="<%= t :message_title, 'Message' %>" data-tooltip><%= t :message_me, 'message me in Canvas' %></label>
<% service_name = s[:service_name] || s[:service].to_s.titleize %>
<label for="social_<%= s[:service] %>" class="social <%= s[:service] %> ic-Label" title="<%= service_name %>" data-tooltip><%= t :service_contact, 'contact %{user} with %{service}', :user => @user_data[:short_name], :service => service_name %></label>
<input class="ic-Input" type="hidden" value="0" name="user_services[<%= s[:service] %>">
<%= check_box_tag "user_services[#{s[:service]}]", 1, s[:visible], :id => "social_#{s[:service]}" %>
</li>
<% @user_data[:user_services].each do |s| %>
<li>
<% service_name = s[:service_name] || s[:service].to_s.titleize %>
<label for="social_<%= s[:service] %>" class="social <%= s[:service] %>" title="<%= service_name %>" data-tooltip><%= t :service_contact, 'contact %{user} with %{service}', :user => @user_data[:short_name], :service => service_name %></label>
<input type="hidden" value="0" name="user_services[<%= s[:service] %>">
<%= check_box_tag "user_services[#{s[:service]}]", 1, s[:visible], :id => "social_#{s[:service]}" %>
</li>
<% end %>
</ul>
</div>
<div class="span6 social-instructions">
<% end %>
</ul>
<div class="social-instructions">
<p>
<%= t(:social_instructions, "Check the contact methods you'd like to be visible to others on your profile.") %><br>
<%= link_to(t(:manage_settings, "Manage Registered Services"), settings_profile_path) %>
</p>
</div>
<% else %>
<p><%= t('#profile.you_have_no_services', "No registered services, you can add some on the *settings* page.", :name => @user_data[:short_name], :wrapper => link_to('\1', settings_profile_path)) %></p>
<% end %>
</div>
<div class="hide-if-editing">
<h3 class="profileHeader"><%= t :ways_to_contact_user, "Contact" %></h3>
<% if @user_data[:user_services].blank? %>
<% if @user != @current_user %>
<p><%= t('#profile.no_registered_services', "No registered services.") %></p>
<% else %>
<p><%= t('#profile.you_have_no_services', "No registered services, you can add some on the *settings* page.", :name => @user_data[:short_name], :wrapper => link_to('\1', settings_profile_path)) %></p>
<% end %>
<% else %>
<ul class="social-links">
<% if current_user_is_account_admin %>
<li><a href="<%= message_user_path(@user) %>" class="social message" title="<%= t :message_title, 'Message' %>" data-tooltip><%= t :message_user_canvas, 'Message %{user} in Canvas', :user => @user_data[:short_name] %></a></li>
<% end %>
<% if @user_data[:user_services].present? && @user.show_user_services %>
<% @user_data[:user_services].select{|s| s[:visible] }.each do |s| %>
<% service_name = s[:service_name] || s[:service].to_s.titleize %>
<li><a href="<%= s[:service_user_link] %>" class="social <%= s[:service] %>" title="<%= service_name %>" data-tooltip><%= t :service_contact, 'contact %{user} with %{service}', :user => @user_data[:short_name], :service => service_name %></a></li>
<% end %>
<% end %>
</ul>
<% end %>
</div>
<div>
<h3 for="profile_bio" class="profileHeader"><%= t :bio, "Biography" %></h3>
<% if @user_data[:bio] %>
<div class="hide-if-editing"><%= raw format_message(@user_data[:bio]).first %></div>
<% else %>
<p class="hide-if-editing"><%= t('user_has_no_bio', "%{user} hasn't added a bio", :user => @user_data[:short_name]) %></p>
<% end %>
<% if @user_data[:can_edit] %>
<div class="show-if-editing">
<textarea class="ic_Input" id="profile_bio" name="user_profile[bio]"><%= @user_data[:bio] %></textarea>
</div>
<% else %>
<p><%= t('#profile.you_have_no_services', "You haven't registered any services, you can add some on the *settings* page.", :name => @user_data[:short_name], :wrapper => link_to('\1', settings_profile_path)) %></p>
<% end %>
</div>
<div class="hide-if-editing">
<h2 class="h5 border border-b"><%= t :ways_to_contact_user, "Ways to contact %{name}", :name => @user_data[:short_name] %></h2>
<ul class="social-links">
<% if current_user_is_account_admin %>
<li><a href="<%= message_user_path(@user) %>" class="social message" title="<%= t :message_title, 'Message' %>" data-tooltip><%= t :message_user_canvas, 'Message %{user} in Canvas', :user => @user_data[:short_name] %></a></li>
<% end %>
<% if @user_data[:user_services].present? && @user.show_user_services %>
<% @user_data[:user_services].select{|s| s[:visible] }.each do |s| %>
<% service_name = s[:service_name] || s[:service].to_s.titleize %>
<li><a href="<%= s[:service_user_link] %>" class="social <%= s[:service] %>" title="<%= service_name %>" data-tooltip><%= t :service_contact, 'contact %{user} with %{service}', :user => @user_data[:short_name], :service => service_name %></a></li>
<% end %>
<% end %>
</ul>
</div>
</div>
</div>
<div class="v-gutter">
<h2 class="h1 border border-b"><label for="profile_bio" style="font-size: 22px"><%= t :bio, "Bio" %></label></h2>
<% if @user_data[:bio] %>
<div class="hide-if-editing"><%= raw format_message(@user_data[:bio]).first %></div>
<% else %>
<p class="hide-if-editing"><%= t('user_has_no_bio', "%{user} hasn't added a bio", :user => @user_data[:short_name]) %></p>
<% end %>
<% if @user_data[:can_edit] %>
<div class="show-if-editing">
<textarea id="profile_bio" name="user_profile[bio]"><%= @user_data[:bio] %></textarea>
</div>
<% end %>
</div>
<div class="row-fluid v-gutter">
<% if @user != @current_user %>
<div class="span6 hide-if-editing">
<h2 class="h1 border border-b"><%= t :know_this_person_as, "You Know This Person as a..." %></h2>
<% if @user_data[:common_contexts] %>
<ul>
<% @user_data[:common_contexts].each do |context| %>
<li><%= context[:roles].join(', ') %> in <a href="<%= context[:html_url] %>"><%= context[:name] %></a></li>
<div>
<% if @user != @current_user %>
<div class="hide-if-editing">
<h3 class="profileHeader"><%= t :user_enrolled, "Enrollments" %></h3>
<% if @user_data[:common_contexts] %>
<ul>
<% @user_data[:common_contexts].each do |context| %>
<li class="profileEnrollment__Items"><%= context[:roles].join(', ') %> in <a href="<%= context[:html_url] %>"><%= context[:name] %></a></li>
<% end %>
</ul>
<% else %>
<p><%= t('nothing_in_common', "You don't have anything in common") %></p>
<% end %>
</ul>
<% else %>
<p><%= t('nothing_in_common', "You don't have anything in common") %></p>
</div>
<% end %>
</div>
<% end %>
<div class="profile_links span6">
<h2 class="h1 border border-b"><%= t :links, "Links" %></h2>
<div class="hide-if-editing">
<% if @user_data[:links].length > 0 %>
<ul>
<% @user_data[:links].each do |link| %>
<li><a href="<%= add_uri_scheme_name(link[:url]) %>"><%= link[:title] %></a></li>
<% end %>
</ul>
<% else %>
<p><%= t :no_links, "%{name} hasn't added any links", :name => @user_data[:short_name] %></p>
<div class="profile_links">
<h3 class="profileHeader"><%= t :links, "Links" %></h3>
<div class="hide-if-editing">
<% if @user_data[:links].length > 0 %>
<ul class="profileLink">
<% @user_data[:links].each do |link| %>
<li class="profileLink__Item">
<i class="icon-link" role="presentation"></i>
<a href="<%= add_uri_scheme_name(link[:url]) %>"><%= link[:title] %></a>
</li>
<% end %>
</ul>
<% else %>
<p><%= t :no_links, "%{name} hasn't added any links", :name => @user_data[:short_name] %></p>
<% end %>
</div>
<% if @user_data[:can_edit] %>
<input type="hidden" name="delete_links" value="1">
<div class="show-if-editing">
<table id="edit_links_table">
<thead>
<th scope="col"><%= t :links_title, 'Title' %></th>
<th></th>
<th scope="col"><%= t :links_url, 'URL' %></th>
</thead>
<tbody id="profile_link_fields"></tbody>
</table>
<button data-event="addLinkField" class="btn btn-small"><%= t :add_link_field, "Add another link" %></button>
</div>
<% end %>
</div>
<% if @user_data[:can_edit] %>
<input type="hidden" name="delete_links" value="1">
<div class="show-if-editing">
<table id="edit_links_table">
<thead>
<th scope="col"><%= t :links_title, 'Title' %></th>
<th></th>
<th scope="col"><%= t :links_url, 'URL' %></th>
</thead>
<tbody id="profile_link_fields"></tbody>
</table>
<button data-event="addLinkField" class="btn btn-small"><%= t :add_link_field, "Add another link" %></button>
<div class="form-actions no-margin-bottom show-if-editing">
<button data-event="cancelEditProfile" class="btn"><%= t('cancel', 'Cancel') %></button>
<button class="btn btn-primary"><%= t('save_profile', 'Save Profile') %></button>
</div>
<% end %>
</div>
<% if @user_data[:can_edit] %>
<div class="form-actions no-margin-bottom show-if-editing">
<button data-event="cancelEditProfile" class="btn"><%= t('cancel', 'Cancel') %></button>
<button class="btn btn-primary"><%= t('save_profile', 'Save Profile') %></button>
</div>
<% end %>
</div>
<% end %>

View File

@ -3,8 +3,12 @@
<% js_bundle :user_logins %>
<% js_env :PASSWORD_POLICY => (@domain_root_account.try(:password_policy) || {}) %>
<fieldset id="login_information">
<legend><%= t('titles.logins', 'Login Information') %></legend>
<table>
<legend>
<h4 class="profileHeader">
<%= t('titles.logins', 'Login Information') %>
</h4>
</legend>
<table class="ic-Table">
<% pseudonyms = @user.all_active_pseudonyms + [nil] %>
<% pseudonyms.each do |pseudonym| %>
<tr class='login <%= 'blank' unless pseudonym %>' style="<%= hidden unless pseudonym %>">
@ -19,7 +23,7 @@
<th scope='row'>
<b class='unique_id'><%= pseudonym && pseudonym.unique_id %></b>
<% if pseudonym && ((pseudonym.sis_user_id && can_do(pseudonym.account, @current_user, :read_sis)) || can_do(pseudonym, @current_user, :manage_sis)) %>
<div style="font-size: 0.8em; padding-left: 20px;">
<div>
<%= before_label('sis_id', 'SIS ID') %> <span id="sis_user_id_<%= pseudonym.id %>" class="sis_user_id"><%= pseudonym.sis_user_id %></span>
</div>
<div style="display:none" class="can_edit_sis_user_id"><%= can_do(pseudonym, @current_user, :manage_sis) %></div>
@ -29,25 +33,25 @@
<%= link_to(pseudonym ? pseudonym.account.name : nbsp, account_url(pseudonym ? pseudonym.account_id : "{{ account_id }}"), :class => 'account_name') %>
</td>
<td class='details'>
<table>
<tr>
<th><%= before_label('last_request', 'Last request') %></th>
<table class="ic-Table--condensed">
<tr class='login_details'>
<td scope="row"><%= before_label('last_request', 'Last request') %></td>
<td><%= datetime_string(pseudonym.try(:last_request_at)) || t('never', "never") %></td>
</tr>
<tr class='login_details' style="<%= hidden if pseudonyms.length > 1 || !pseudonym %>">
<th><%= before_label('current_login', 'Current login') %></th>
<td scope="row"><%= before_label('current_login', 'Current login') %></td>
<td><%= datetime_string(pseudonym.try(:current_login_at)) || t('never', "never") %></td>
</tr>
<tr class='login_details' style="<%= hidden if pseudonyms.length > 1 || !pseudonym %>">
<th><%= before_label('current_ip', 'Current login IP') %></th>
<td scope="row"><%= before_label('current_ip', 'Current login IP') %></td>
<td><%= pseudonym.try(:current_login_ip) || t('none', "none") %></td>
</tr>
<tr class='login_details' style="<%= hidden if pseudonyms.length > 1 || !pseudonym %>">
<th><%= before_label('last_login', 'Last login') %></th>
<td scope="row"><%= before_label('last_login', 'Last login') %></td>
<td><%= datetime_string(pseudonym.try(:last_login_at)) || t('never', "never") %></td>
</tr>
<tr class='login_details' style="<%= hidden if pseudonyms.length > 1 || !pseudonym %>">
<th><%= before_label('last_ip', 'Last login IP') %></th>
<td scope="row"><%= before_label('last_ip', 'Last login IP') %></td>
<td><%= pseudonym.try(:last_login_ip) || t('none', "none") %></td>
</tr>
</table>
@ -69,7 +73,7 @@
<% can_reset_mfa = @user.otp_secret_key && can_do(@user, @current_user, :reset_mfa) %>
<% if can_add_pseudonym || can_reset_mfa %>
<tr class="add_holder">
<td colspan="4" style="font-size: 0.8em;">
<td colspan="5">
<% if can_add_pseudonym %>
<a href="#" rel="<%= user_pseudonyms_url(@user.id) %>" class="add_pseudonym_link"><%= t('add_login', 'Add Login') %></a>
<% end %>
@ -142,4 +146,4 @@
<button type="submit" class="btn btn-primary submit_button"><%= t('buttons.update_login', 'Update Login') %></button>
</div>
<% end %>
<% end %>
<% end %>

View File

@ -155,7 +155,7 @@ h3.beta {
.method_details h3.endpoint {
font-weight: normal;
font-size: 14px;
font-family: Monaco, Consolas, Courier, monospace;
font-family: Monaco, Lucida Console, monospace;
padding: 6px 10px;
margin-top: 18px;
color: #333;
@ -317,7 +317,7 @@ table.request-params, table.request-params th, table.request-params td {
table.request-params td {
border-bottom: 1px solid #ccc;
vertical-align: text-top;
font-family: Monaco;
font-family: Monaco, Lucida Console, monospace;
font-size: 12px;
}
table.request-params td.param-desc {

View File

@ -9,18 +9,26 @@ module TatlTael
@git_dir = git_dir
end
def changes(git_dir)
def changes
command = "git diff-tree --no-commit-id --name-status -r HEAD"
raw_changes = shell(command, git_dir)
raw_changes = shell(command)
raw_changes.split("\n").map do |raw_change|
status, path = raw_change.split("\t")
TatlTael::Change.new(status, path)
end
end
def wip?
first_line =~ /\A(\(|\[)?wip\b/i ? true : false
end
private
def shell(command, git_dir)
def first_line
`git log --pretty=%s -1 HEAD`.strip
end
def shell(command)
if git_dir
Dir.chdir(git_dir) do
Kernel.send(:`, command)

View File

@ -1,14 +1,18 @@
require_relative 'git_proxy'
require 'forwardable'
module TatlTael
class Linter
extend ::Forwardable
attr_reader :git
private :git
def_delegator :git, :wip?
attr_reader :git_dir
private :git_dir
def initialize(git_dir:, git: nil)
def initialize(git_dir: ".", git: nil)
@git_dir = git_dir
@git = git || TatlTael::GitProxy.new(git_dir)
end
@ -50,7 +54,7 @@ module TatlTael
end
def changes
@changes ||= git.changes(git_dir)
@changes ||= git.changes
end
end
end

View File

@ -4,7 +4,7 @@ module Canvas
module Cdn
class S3Uploader
attr_accessor :bucket, :config
attr_accessor :bucket, :config, :mutex
def initialize(folder='dist')
require 'aws-sdk'
@ -13,6 +13,7 @@ module Canvas
@s3 = AWS::S3.new(access_key_id: config.aws_access_key_id,
secret_access_key: config.aws_secret_access_key)
@bucket = @s3.buckets[config.bucket]
@mutex = Mutex.new
end
def local_files
@ -59,7 +60,7 @@ module Canvas
def upload_file(remote_path)
local_path = Pathname.new("#{Rails.public_path}/#{remote_path}")
return if (local_path.extname == '.gz') || local_path.directory?
s3_object = bucket.objects[remote_path]
s3_object = mutex.synchronize { bucket.objects[remote_path] }
return log("skipping already existing #{remote_path}") if s3_object.exists?
options = options_for(local_path)
s3_object.write(handle_compression(local_path, options), options)

View File

@ -43,14 +43,10 @@ module CC::Exporter::Epub::Converters
if should_convert_file?(unescaped)
match[attr] = converted_media_path(unescaped)
else
match.replace(<<-SPAN_TAG)
<span>
#{I18n.t(<<-TEXT, filename: File.basename(unescaped))
File %{filename} could not be included in the ePub document. Please see separate zip file for access.
TEXT
}
</span>
SPAN_TAG
message = I18n.t(<<-TEXT, filename: File.basename(unescaped))
File %{filename} could not be included in the ePub document. Please see separate zip file for access.
TEXT
match.replace(format('<span>%s</span>', ERB::Util.h(message)))
end
end
end

View File

@ -128,7 +128,7 @@ module FeatureFlags
(retval.default? || retval.context_type == 'Account' && retval.context_id == Account.site_admin.id)
if is_root_account
# create a virtual feature flag in "off" state
retval = self.feature_flags.build feature: feature, state: 'off' unless retval.hidden?
retval = self.feature_flags.temp_record feature: feature, state: 'off' unless retval.hidden?
else
# the feature doesn't exist beneath the root account until the root account opts in
return @feature_flag_cache[feature] = nil

View File

@ -31,6 +31,12 @@ end
linter = TatlTael::Linter.new(git_dir: git_dir)
# don't run for wips
if linter.wip?
puts "WIP detected, TatlTael will not run."
exit 0
end
linter.ensure_specs do
post("Your commit does not include specs."\
" Please add some to verify your changes.")

View File

@ -0,0 +1,58 @@
define [
'jquery'
'compiled/views/SisButtonView'
'Backbone'
], ($, SisButtonView, Backbone) ->
class AssignmentStub extends Backbone.Model
url: '/fake'
postToSIS: (postToSisBoolean) =>
return @get 'post_to_sis' unless arguments.length > 0
@set 'post_to_sis', postToSisBoolean
class QuizStub extends Backbone.Model
url: '/fake'
postToSIS: (postToSisBoolean) =>
return @get 'post_to_sis' unless arguments.length > 0
@set 'post_to_sis', postToSisBoolean
module 'SisButtonView',
setup: ->
@assignment = new AssignmentStub()
@quiz = new QuizStub()
@quiz.set('toggle_post_to_sis_url', '/some_other_url')
test 'properly populates initial settings', ->
@assignment.set('post_to_sis', true)
@quiz.set('post_to_sis', false)
@view1 = new SisButtonView(model: @assignment)
@view2 = new SisButtonView(model: @quiz)
@view1.render()
@view2.render()
equal @view1.$input.attr('title'), 'Post grade to SIS enabled. Click to toggle.'
equal @view2.$input.attr('title'), 'Post grade to SIS disabled. Click to toggle.'
test 'properly toggles model sis status when clicked', ->
@assignment.set('post_to_sis', false)
@view = new SisButtonView(model: @assignment)
@view.render()
@view.$el.click()
ok @assignment.postToSIS()
@view.$el.click()
ok !@assignment.postToSIS()
test 'properly saves model with a custom url if present', ->
@stub @quiz, 'save', (attributes, options) ->
ok options['url'], '/some_other_url'
@quiz.set('post_to_sis', false)
@view = new SisButtonView(model: @quiz)
@view.render()
@view.$el.click()
ok @quiz.postToSIS()
test 'properly associates button label via aria-describedby', ->
@assignment.set('id', '1')
@view = new SisButtonView(model: @assignment)
@view.render()
equal @view.$input.attr('aria-describedby'), 'sis-status-label-1'
equal @view.$label.attr('id'), 'sis-status-label-1'

View File

@ -116,6 +116,8 @@ define [
read_grades: options.canReadGrades
}
ENV.POST_TO_SIS = options.post_to_sis
view = new AssignmentListItemView(model: model)
view.$el.appendTo $('#fixtures')
view.render()
@ -171,6 +173,18 @@ define [
ok !view.vddTooltipView
ok !view.editAssignmentView
test "initializes sis toggle if post to sis enabled", ->
view = createView(@model, canManage: true, post_to_sis: true)
ok view.sisButtonView
test "does not initialize sis toggle if post to sis disabled", ->
view = createView(@model, canManage: true, post_to_sis: false)
ok !view.sisButtonView
test "does not initialize sis toggle if sis enabled but can't manage", ->
view = createView(@model, canManage: false, post_to_sis: true)
ok !view.sisButtonView
test "upatePublishState toggles ig-published", ->
view = createView(@model, canManage: true)

View File

@ -10,12 +10,20 @@ define [
fixtures = $('#fixtures')
createView = (quiz) ->
createView = (quiz, options={}) ->
quiz ?= new Quiz(id: 1, title: 'Foo')
icon = new PublishIconView(model: quiz)
view = new QuizItemView(model: quiz, publishIconView: icon)
ENV.PERMISSIONS = {
manage: options.canManage
}
ENV.FLAGS = {
post_to_sis_enabled: options.post_to_sis
}
view = new QuizItemView(model: quiz, publishIconView: icon)
view.$el.appendTo $('#fixtures')
view.render()
@ -33,6 +41,20 @@ define [
view = createView(quiz)
equal view.$('.ig-admin').length, 0
test "initializes sis toggle if post to sis enabled", ->
quiz = new Quiz(id: 1, title: 'Foo', can_update: true)
view = createView(quiz, canManage: true, post_to_sis: true)
ok view.sisButtonView
test "does not initialize sis toggle if post to sis disabled", ->
quiz = new Quiz(id: 1, title: 'Foo', can_update: true)
view = createView(quiz, canManage: true, post_to_sis: false)
ok !view.sisButtonView
test "does not initialize sis toggle if sis enabled but can't manage", ->
quiz = new Quiz(id: 1, title: 'Foo', can_update: false)
view = createView(quiz, canManage: false, post_to_sis: false)
ok !view.sisButtonView
test 'udpates publish status when model changes', ->
quiz = new Quiz(id: 1, title: 'Foo', published: false)
@ -43,7 +65,6 @@ define [
quiz.set("published", true)
ok view.$el.find(".ig-row").hasClass("ig-published")
test 'prompts confirm for delete', ->
quiz = new Quiz(id: 1, title: 'Foo', can_update: true)
view = createView(quiz)

View File

@ -519,6 +519,15 @@ describe GradebooksController do
end
end
describe "POST 'submissions_zip_upload'" do
it "requires authentication" do
course
assignment_model
post 'submissions_zip_upload', :course_id => @course.id, :assignment_id => @assignment.id, :submissions_zip => 'dummy'
assert_unauthorized
end
end
describe "POST 'update_submission'" do
it "allows adding comments for submission" do
user_session(@teacher)

View File

@ -611,7 +611,7 @@ describe Assignment do
end
it "uses the canvas default" do
expect(@assignment.grading_standard_or_default.title).to eql "Default Grading Standard"
expect(@assignment.grading_standard_or_default.title).to eql "Default Grading Scheme"
end
end

View File

@ -55,7 +55,7 @@ module BroadcastPolicies
let(:policy) do
SubmissionPolicy.new(submission).tap do |policy|
policy.stubs(:user_active_invited_or_concluded?).returns(true)
policy.stubs(:user_active_or_invited?).returns(true)
policy.stubs(:user_has_visibility?).returns(true)
end
end
@ -159,7 +159,7 @@ module BroadcastPolicies
specify { wont_send_when{ course.stubs(:available?).returns false}}
specify { wont_send_when{ submission.stubs(:quiz_submission).returns stub }}
specify { wont_send_when{ assignment.stubs(:published?).returns false}}
specify { wont_send_when{ policy.stubs(:user_active_invited_or_concluded?).returns(false)}}
specify { wont_send_when{ policy.stubs(:user_active_or_invited?).returns(false)}}
specify { wont_send_when{ course.stubs(:concluded?).returns true }}
end

View File

@ -222,4 +222,54 @@ describe EpubExport do
end
end
end
describe '#set_locale' do
let_once(:cartridge_path) do
File.join(File.dirname(__FILE__), "/../fixtures/migration/unicode-filename-test-export.imscc")
end
let_once(:content_export) do
@course.content_exports.create({
user: @student
}).tap do |content_export|
content_export.create_attachment({
context: @course,
filename: File.basename(cartridge_path),
uploaded_data: File.open(cartridge_path)
})
end
end
let_once(:epub_export) do
@course.epub_exports.create({
user: @student,
content_export: content_export
})
end
it 'is called during export and resets locale after' do
epub_export.expects(:infer_locale).once
.with(context: @course, user: @student, root_account: @course.root_account)
.returns(:ru)
epub_export.convert_to_epub_without_send_later
expect(I18n.locale).to be :en
end
it 'sets locale based on user preference' do
@student.update_attribute(:locale, 'es')
epub_export.reload.send(:set_locale)
expect(I18n.locale).to eq :es
end
it 'sets locale based on course override' do
@course.update_attribute(:locale, 'da')
epub_export.reload.send(:set_locale)
expect(I18n.locale).to eq :da
end
it 'allows course locale to override user locale' do
@student.update_attribute(:locale, 'es')
@course.update_attribute(:locale, 'da')
epub_export.reload.send(:set_locale)
expect(I18n.locale).to eq :da
end
end
end

View File

@ -29,7 +29,8 @@ describe FeatureFlag do
'account_feature' => Feature.new(feature: 'account_feature', applies_to: 'Account'),
'course_feature' => Feature.new(feature: 'course_feature', applies_to: 'Course'),
'user_feature' => Feature.new(feature: 'user_feature', applies_to: 'User'),
'hidden_feature' => Feature.new(feature: 'hidden_feature', state: 'hidden', applies_to: 'Course')
'hidden_feature' => Feature.new(feature: 'hidden_feature', state: 'hidden', applies_to: 'Course'),
'hidden_root_opt_in_feature' => Feature.new(feature: 'hidden_feature', state: 'hidden', applies_to: 'Course', root_opt_in: true)
})
end
@ -108,5 +109,10 @@ describe FeatureFlag do
t_sub_account.enable_feature! :hidden_feature
expect(t_sub_account.lookup_feature_flag(:hidden_feature)).not_to be_unhides_feature
end
it "should be true on a sub-account root-opt-in feature flag with no root or site admin flags set" do
t_course.enable_feature! :hidden_root_opt_in_feature
expect(t_course.feature_flag(:hidden_root_opt_in_feature)).to be_unhides_feature
end
end
end

View File

@ -261,6 +261,21 @@ describe Submission do
expect(@submission.messages_sent).to be_include('Submission Graded')
end
it "should not create a message for a soft-concluded student" do
submission_spec_model
@course.start_at = 2.weeks.ago
@course.conclude_at = 1.weeks.ago
@course.restrict_enrollments_to_course_dates = true
@course.save!
@cc = @user.communication_channels.create(:path => "somewhere")
@submission.reload
expect(@submission.assignment).to eql(@assignment)
expect(@submission.assignment.state).to eql(:published)
@submission.grade_it!
expect(@submission.messages_sent).to_not be_include('Submission Graded')
end
it "notifies observers" do
submission_spec_model
course_with_observer(course: @course, associated_user_id: @user.id, active_all: true, active_cc: true)

View File

@ -577,61 +577,6 @@ describe "assignments" do
wait_for_ajaximations
expect(f("#content")).not_to contain_css('#assignment_post_to_sis')
end
it 'should display post to SIS icon on assignments page when enabled', priority: "2", test_id: 649314 do
Account.default.set_feature_flag!('post_grades', 'on')
@a1 = @course.assignments.create!(:name => 'assignment 1', :post_to_sis => true)
@a2 = @course.assignments.create!(:name => 'assignment 2', :post_to_sis => false)
@a3 = @course.assignments.create!(:name => 'assignment 3', :post_to_sis => true)
get "/courses/#{@course.id}/assignments/"
wait_for_ajaximations
expect(find_all('.post-to-sis-status.enabled').count).to be 2
expect(find_all('.post-to-sis-status.disabled').count).to be 1
Account.default.set_feature_flag!('post_grades', 'off')
get "/courses/#{@course.id}/assignments/"
wait_for_ajaximations
expect(find_all('.post-to-sis-status.enabled').count).to be 0
expect(find_all('.post-to-sis-status.disabled').count).to be 0
end
it 'should toggle the post to SIS feature when clicked', priority: "2", test_id: 649315 do
Account.default.set_feature_flag!('post_grades', 'on')
@a1 = @course.assignments.create!(:name => 'assignment 1', :post_to_sis => true)
@a2 = @course.assignments.create!(:name => 'assignment 2', :post_to_sis => false)
@a3 = @course.assignments.create!(:name => 'assignment 3', :post_to_sis => true)
get "/courses/#{@course.id}/assignments/"
wait_for_ajaximations
enabled = find_all('.post-to-sis-status.enabled')
disabled = find_all('.post-to-sis-status.disabled')
expect(enabled.count).to be 2
expect(disabled.count).to be 1
enabled.each(&:click)
disabled.each(&:click)
wait_for_ajaximations
@a1.reload
@a2.reload
@a3.reload
expect(@a1.post_to_sis).to be_falsey
expect(@a2.post_to_sis).to be_truthy
expect(@a3.post_to_sis).to be_falsey
expect(find_all('.post-to-sis-status.enabled').count).to be 1
expect(find_all('.post-to-sis-status.disabled').count).to be 2
end
end
it 'should go to the assignment index page from left nav', priority: "1", test_id: 108724 do

View File

@ -3,6 +3,7 @@ require_relative '../../helpers/groups_common'
describe "gradebook2" do
include_context "in-process server selenium tests"
include_context "gradebook_components"
include Gradebook2Common
include GroupsCommon
@ -227,6 +228,20 @@ describe "gradebook2" do
expect(f("#content")).not_to contain_jqcss('.student-placeholder:visible')
end
it "should hide and show notes", priority: "2", test_id: 164224 do
get "/courses/#{@course.id}/gradebook2"
# show notes column
gradebook_settings_cog.click
show_notes.click
expect(f("#content")).to contain_jqcss('.custom_column:visible')
# hide notes column
gradebook_settings_cog.click
hide_notes.click
expect(f("#content")).not_to contain_jqcss('.custom_column:visible')
end
context "downloading and uploading submissions" do
it "updates the dropdown menu after downloading and processes submission uploads" do
# Given I have a student with an uploaded submission

View File

@ -7,9 +7,17 @@ describe "gradebook2 - total points toggle" do
let!(:setup) { gradebook_data_setup }
def should_show_percentages
wait_for_ajaximations
ff(".slick-row .slick-cell:nth-child(5)").each { |total| expect(total.text).to match(/%/) }
end
def should_show_points
expected_points = 15, 10, 10
ff(".slick-row .slick-cell:nth-child(5)").each do |total|
expect(total.text).to match(/\A#{expected_points.shift}$/)
end
end
def open_display_dialog
f("#total_dropdown").click
f(".toggle_percent").click
@ -31,6 +39,19 @@ describe "gradebook2 - total points toggle" do
submit_dialog(dialog, '.ui-button')
end
it "setting group weights should switch to percentage", test_id: 164231, priority: "2" do
get "/courses/#{@course.id}/gradebook2"
toggle_grade_display
should_show_points
group = AssignmentGroup.where(name: @group.name).first
set_group_weight(group, 50)
disable_group_weight
should_show_percentages
end
it "should warn the teacher that studens will see a change" do
get "/courses/#{@course.id}/gradebook2"
open_display_dialog
@ -43,10 +64,7 @@ describe "gradebook2 - total points toggle" do
should_show_percentages
toggle_grade_display
expected_points = 15, 10, 10
ff(".slick-row .slick-cell:nth-child(5)").each do |total|
expect(total.text).to match(/\A#{expected_points.shift}$/)
end
should_show_points
toggle_grade_display
should_show_percentages

View File

@ -401,6 +401,7 @@ describe "new groups" do
end
it 'should create a group with a given name and limit', priority: "2", test_id: 94166 do
skip("broken qa-729")
group_test_setup(5,1,1)
3.times do |n|
add_user_to_group(@students[n+1], @testgroup.first, false)

View File

@ -4,6 +4,8 @@ module Gradebook2Common
shared_context 'gradebook_components' do
let(:gradebook_settings_cog) { f('#gradebook_settings') }
let(:group_weights_menu) { f('[aria-controls="assignment_group_weights_dialog"]') }
let(:show_notes) { fj('li a:contains("Show Notes Column")') }
let(:hide_notes) { f(".hide") }
end
shared_context 'reusable_course' do
let(:test_course) { course(active_course: true) }
@ -352,6 +354,22 @@ module Gradebook2Common
expect(@course.reload.group_weighting_scheme).to eq 'percent'
end
def disable_group_weight
f('#gradebook_settings').click
f('[aria-controls="assignment_group_weights_dialog"]').click
dialog = f('#assignment_group_weights_dialog')
expect(dialog).to be_displayed
group_check = dialog.find_element(:id, 'group_weighting_scheme')
keep_trying_until do
group_check.click
expect(is_checked('#group_weighting_scheme')).to be_falsey
end
fj('.ui-button:contains("Save")').click
refresh_page
end
def validate_group_weight_text(assignment_groups, weight_numbers)
assignment_groups.each_with_index do |ag, i|
heading = fj(".slick-column-name:contains('#{ag.name}') .assignment-points-possible")

View File

@ -141,7 +141,10 @@ end
shared_examples 'people_page' do |context|
it "should allow group users to see group registered services page", priority: pick_priority(context, student: "1", teacher: "2"),test_id: pick_test_id(context, student: 323329, teacher: 324926) do
get people_page
expect_new_page_load { fln('View Registered Services').click }
expect_new_page_load do
f("#people-options .Button").click
fln('View Registered Services').click
end
# Checks that we are on the Registered Services page
expect(f('.btn.button-sidebar-wide')).to be_displayed
end
@ -235,4 +238,3 @@ shared_examples 'conferences_page' do |context|
expect(f('#concluded-conference-list')).to include_text('There are no concluded conferences')
end
end

View File

@ -22,7 +22,10 @@ describe "people" do
end
def create_student_group(group_text = "new student group")
expect_new_page_load { fln('View User Groups').click }
expect_new_page_load do
f("#people-options .Button").click
fln('View User Groups').click
end
open_student_group_dialog
inputs = ffj('input:visible')
replace_content(inputs[0], group_text)
@ -167,6 +170,7 @@ describe "people" do
end
it "should display activity report on clicking Student Interaction button", priority: "1", test_id: 244446 do
f("#people-options .Button").click
fln("Student Interactions Report").click
wait_for_ajaximations
user_name = f(".user_name").text
@ -204,6 +208,7 @@ describe "people" do
end
it "should navigate to registered services on profile page" do
f("#people-options .Button").click
fln('View Registered Services').click
fln('Link web services to my account').click
expect(f('#unregistered_services')).to be_displayed
@ -214,6 +219,7 @@ describe "people" do
end
it "should test self sign up help functionality" do
f("#people-options .Button").click
expect_new_page_load { fln('View User Groups').click }
open_student_group_dialog
fj('.self_signup_help_link:visible').click
@ -222,6 +228,7 @@ describe "people" do
end
it "should test self sign up functionality" do
f("#people-options .Button").click
expect_new_page_load { fln('View User Groups').click }
dialog = open_student_group_dialog
dialog.find_element(:css, '#category_enable_self_signup').click
@ -231,7 +238,10 @@ describe "people" do
it "should test self sign up / group structure functionality" do
group_count = "4"
expect_new_page_load { fln('View User Groups').click }
expect_new_page_load do
f("#people-options .Button").click
fln('View User Groups').click
end
dialog = open_student_group_dialog
dialog.find_element(:css, '#category_enable_self_signup').click
dialog.find_element(:css, '#category_create_group_count').send_keys(group_count)
@ -245,7 +255,10 @@ describe "people" do
enroll_more_students
group_count = "4"
expect_new_page_load { fln('View User Groups').click }
expect_new_page_load do
f("#people-options .Button").click
fln('View User Groups').click
end
dialog = open_student_group_dialog
dialog.find_element(:css, '#category_split_groups').click
replace_content(f('#category_split_group_count'), group_count)
@ -286,7 +299,10 @@ describe "people" do
enroll_more_students
group_count = 4
expect_new_page_load { fln('View User Groups').click }
expect_new_page_load do
f("#people-options .Button").click
fln('View User Groups').click
end
open_student_group_dialog
submit_form('#add_category_form')
wait_for_ajaximations
@ -309,7 +325,10 @@ describe "people" do
it "should test prior enrollment functionality" do
@course.complete
get "/courses/#{@course.id}/users"
expect_new_page_load { fln('View Prior Enrollments').click }
expect_new_page_load do
f("#people-options .Button").click
fln('View Prior Enrollments').click
end
expect(f('#users')).to include_text(@student_1.name)
end
@ -399,7 +418,7 @@ describe "people" do
student = create_user("student@example.com")
enroll_student(student)
get "/courses/#{@course.id}/users"
ff(".icon-settings")[1].click
f(".StudentEnrollment .icon-settings").click
fln("Edit Sections").click
f(".token_input.browsable").click
section_input_element = driver.find_element(:name, "token_capture")
@ -416,7 +435,7 @@ describe "people" do
@course.enroll_student(@student, allow_multiple_enrollments: true)
@course.enroll_student(@student, section: @section2, allow_multiple_enrollments: true)
get "/courses/#{@course.id}/users"
ff(".icon-settings")[1].click
f(".StudentEnrollment .icon-settings").click
fln("Edit Sections").click
fln("Remove user from section2").click
ff('.ui-button-text')[1].click

View File

@ -180,8 +180,8 @@ describe "profile" do
register_form = f('#register_sms_number')
register_form.find_element(:css, '.sms_number').send_keys(test_cell_number)
click_option('select.user_selected.carrier', 'AT&T')
driver.action.send_keys(:tab).perform
submit_form(register_form)
sleep 1 # wait a moment before we close any dialogs, since this spec fails intermittently ... this way we can catch any formError thingies in the video capture
wait_for_ajaximations
close_visible_dialog
keep_trying_until { expect(f('.other_channels .path')).to include_text(test_cell_number) }

View File

@ -67,77 +67,6 @@ describe "quizzes" do
expect(group_form.find_element(:css, '.group_display.name')).to include_text('new group')
end
it 'should display post to SIS icon on quiz page when enabled' do
Account.default.set_feature_flag!('post_grades', 'on')
@q1 = quiz_create
@q2 = quiz_create
@q3 = quiz_create
@q1.post_to_sis = true
@q2.post_to_sis = false
@q3.post_to_sis = true
@q1.save!
@q2.save!
@q3.save!
get "/courses/#{@course.id}/quizzes/"
wait_for_ajaximations
expect(find_all('.post-to-sis-status.enabled').count).to be 2
expect(find_all('.post-to-sis-status.disabled').count).to be 1
Account.default.set_feature_flag!('post_grades', 'off')
get "/courses/#{@course.id}/quizzes/"
wait_for_ajaximations
expect(find_all('.post-to-sis-status.enabled').count).to be 0
expect(find_all('.post-to-sis-status.disabled').count).to be 0
end
it 'should display post to SIS icon on quiz page when enabled' do
Account.default.set_feature_flag!('post_grades', 'on')
@q1 = quiz_create
@q2 = quiz_create
@q3 = quiz_create
@q1.post_to_sis = true
@q2.post_to_sis = false
@q3.post_to_sis = true
@q1.save!
@q2.save!
@q3.save!
get "/courses/#{@course.id}/quizzes/"
wait_for_ajaximations
enabled = find_all('.post-to-sis-status.enabled')
disabled = find_all('.post-to-sis-status.disabled')
expect(enabled.count).to be 2
expect(disabled.count).to be 1
enabled.each(&:click)
disabled.each(&:click)
wait_for_ajaximations
@q1.reload
@q2.reload
@q3.reload
expect(@q1.post_to_sis?).to be_falsey
expect(@q2.post_to_sis?).to be_truthy
expect(@q3.post_to_sis?).to be_falsey
expect(find_all('.post-to-sis-status.enabled').count).to be 1
expect(find_all('.post-to-sis-status.disabled').count).to be 2
end
it "should update a question group", priority: "1", test_id: 210061 do
skip('fragile')
get "/courses/#{@course.id}/quizzes/new"

View File

@ -135,7 +135,7 @@ module CustomSeleniumActions
end
def is_checked(css_selector)
driver.execute_script('return $("'+css_selector+'").prop("checked")')
!!fj(css_selector)[:checked]
end
def get_value(selector)