Commit 206ea8ca by Brian Talbot Committed by Andy Armstrong

Studio: adding UI and styling for component-level access modal

parent 561c57db
...@@ -183,6 +183,7 @@ $color-ready: $green; ...@@ -183,6 +183,7 @@ $color-ready: $green;
$color-warning: $orange-l2; $color-warning: $orange-l2;
$color-error: $red-l2; $color-error: $red-l2;
$color-staff-only: $black; $color-staff-only: $black;
$color-visibility-set: $black;
$color-heading-base: $gray-d2; $color-heading-base: $gray-d2;
$color-copy-base: $gray-l1; $color-copy-base: $gray-l1;
......
// studio - elements - forms // studio - elements - forms
// ==================== // ====================
// Table of Contents // Table of Contents
// * +Forms - General // * +Forms - General
// * +Field - Is Editable // * +Field - Is Editable
// * +Field - With Error // * +Field - With Error
...@@ -12,7 +12,23 @@ ...@@ -12,7 +12,23 @@
// * +Form - Grandfathered // * +Form - Grandfathered
// +Forms - General // +Forms - General
// ==================== // ====================
// element-specific utilities
// --------------------
// UI: checkbox/radio inputs
%input-tickable {
~ label {
color: $color-copy-base;
}
// STATE: checked/selected
&:checked ~ label {
@extend %t-strong;
color: $ui-action-primary-color-focus;
}
}
input[type="text"], input[type="text"],
input[type="email"], input[type="email"],
input[type="password"], input[type="password"],
...@@ -107,8 +123,18 @@ form { ...@@ -107,8 +123,18 @@ form {
} }
} }
// CASE: checkbox input
.field-checkbox .input-checkbox {
@extend %input-tickable;
}
// CASE: radio input
.field-radio .input-radio {
@extend %input-tickable;
}
// CASE: file input // CASE: file input
input[type=file] { input[type="file"] {
@extend %t-copy-sub1; @extend %t-copy-sub1;
} }
......
...@@ -52,6 +52,45 @@ ...@@ -52,6 +52,45 @@
} }
} }
// UI: summary messages
.summary-message {
margin-bottom: $baseline;
padding: ($baseline*0.75);
background: $gray-d3;
.icon, .copy {
display: inline-block;
vertical-align: top;
}
.icon {
@extend %t-icon4;
@include margin-right($baseline/2);
color: $white;
}
.copy {
@extend %t-copy-sub1;
max-width: 85%;
color: $white;
}
}
// CASE: Warning summary message
.summary-message-warning {
border-top: ($baseline/5) solid $color-warning;
.icon {
color: $color-warning;
}
}
// visual dividers
.divider-visual {
margin: ($baseline*0.75) 0;
border: ($baseline/20) solid $gray-l4;
}
// sections within a modal // sections within a modal
.modal-section { .modal-section {
margin-bottom: ($baseline*0.75); margin-bottom: ($baseline*0.75);
...@@ -64,11 +103,20 @@ ...@@ -64,11 +103,20 @@
.modal-section-title { .modal-section-title {
@extend %t-title6; @extend %t-title6;
margin: 0 0 ($baseline/2) 0; margin: 0 0 ($baseline/2) 0;
border-bottom: 1px solid $gray-l4; border-bottom: ($baseline/10) solid $gray-l4;
padding-bottom: ($baseline/4); padding-bottom: ($baseline/4);
color: $gray-d2; color: $gray-d2;
} }
.modal-subsection-title {
@extend %t-title8;
@extend %t-strong;
margin-bottom: ($baseline/4);
text-transform: uppercase;
letter-spacing: 0.1;
color: $gray-l2;
}
.modal-section-content { .modal-section-content {
.list-fields, .list-actions { .list-fields, .list-actions {
...@@ -238,143 +286,6 @@ ...@@ -238,143 +286,6 @@
} }
} }
// outline: edit item settings
.wrapper-modal-window-bulkpublish-section,
.wrapper-modal-window-bulkpublish-subsection,
.wrapper-modal-window-bulkpublish-unit,
.course-outline-modal {
.list-fields {
.field {
display: inline-block;
vertical-align: top;
margin-right: ($baseline/2);
margin-bottom: ($baseline/4);
label {
@extend %t-copy-sub1;
@extend %t-strong;
@include transition(color $tmg-f3 ease-in-out 0s);
margin: 0 0 ($baseline/4) 0;
&.is-focused {
color: $blue;
}
}
input, textarea {
@extend %t-copy-base;
@include transition(all $tmg-f2 ease-in-out 0s);
height: 100%;
width: 100%;
padding: ($baseline/2);
// CASE: long length
&.long {
width: 100%;
}
// CASE: short length
&.short {
width: 25%;
}
}
// CASE: specific release + due times/dates
.start-date,
.start-time,
.due-date,
.due-time {
width: ($baseline*7);
}
.tip {
@extend %t-copy-sub1;
@include transition(color, 0.15s, ease-in-out);
display: block;
margin-top: ($baseline/4);
color: $gray-l2;
}
.tip-warning {
color: $gray-d2;
}
}
// CASE: type-based input
.field-text {
// TODO: refactor the _forms.scss partial to allow for this area to inherit from it
label, input, textarea {
display: block;
}
}
// CASE: select input
.field-select {
.label, .input {
display: inline-block;
vertical-align: middle;
}
.label {
margin-right: ($baseline/2);
}
.input {
width: 100%;
}
// CASE: checkbox input
.field-checkbox {
.label, label {
margin-bottom: 0;
}
}
}
}
// UI: grading section
.edit-settings-grading {
.grading-type {
margin-bottom: $baseline;
}
}
// UI: staff lock section
.edit-staff-lock {
.checkbox-cosmetic .input-checkbox {
@extend %cont-text-sr;
// CASE: unchecked
~ .tip-warning {
display: block;
}
// CASE: checked
&:checked {
~ .tip-warning {
display: none;
}
}
}
// needed to override poorly scoped margin-bottom on any label element in a view (from _forms.scss)
.checkbox-cosmetic .label {
margin-bottom: 0;
}
}
}
// xblock custom actions // xblock custom actions
.modal-window .editor-with-buttons { .modal-window .editor-with-buttons {
margin-bottom: ($baseline*3); margin-bottom: ($baseline*3);
...@@ -394,7 +305,7 @@ ...@@ -394,7 +305,7 @@
} }
// special overrides for video module editor/hidden tab editors // MODAL TYPE: component - video modal (includes special overrides for xblock-related editing view)
.modal-lg.modal-type-video { .modal-lg.modal-type-video {
.modal-content { .modal-content {
...@@ -517,4 +428,225 @@ ...@@ -517,4 +428,225 @@
opacity: 0.5; opacity: 0.5;
filter: alpha(opacity=50); filter: alpha(opacity=50);
} }
// MODAL TYPE: component - visibility modal
.xblock-visibility_view {
.visibility-controls-secondary {
max-height: 100%;
overflow-y: scroll;
@include margin(($baseline*0.75), 0, 0, $baseline);
}
.visibility-controls-group {
@extend %wipe-last-child;
margin-bottom: $baseline;
}
// UI: form fields
.list-fields {
.field {
@extend %wipe-last-child;
margin-bottom: ($baseline/4);
label {
@extend %t-copy-sub1;
}
}
// UI: radio and checkbox inputs
.field-radio, .field-checkbox {
label {
@include margin-left($baseline/4);
}
}
}
// CASE: content group has been removed
.field-visibility-content-group.was-removed {
.input-checkbox:checked ~ label {
color: $color-error;
}
.note {
@extend %t-copy-sub2;
@extend %t-regular;
display: block;
color: $color-error;
}
}
// CASE: no groups configured for visibility
.is-not-configured {
@extend %no-content;
padding: ($baseline);
@include text-align(left); // reset for %no-content's default styling
.title {
@extend %t-title6;
font-weight: 600; // needed for poorly scoped .title rule in modals
margin: 0 0 ($baseline/2) 0; // needed for poorly scoped .title rule in modals
}
.copy {
@extend %t-copy-sub1;
p {
@extend %wipe-last-child;
margin-bottom: $baseline;
}
}
&.has-actions {
.actions {
margin-top: $baseline;
}
.action {
@include margin-left(0); // reset for %no-content's default styling
}
}
}
}
// MODAL TYPE: outline - edit item settings
.wrapper-modal-window-bulkpublish-section,
.wrapper-modal-window-bulkpublish-subsection,
.wrapper-modal-window-bulkpublish-unit,
.course-outline-modal {
.list-fields {
.field {
display: inline-block;
vertical-align: top;
@include margin-right($baseline/2);
margin-bottom: ($baseline/4);
label {
@extend %t-copy-sub1;
@extend %t-strong;
@include transition(color $tmg-f3 ease-in-out 0s);
margin: 0 0 ($baseline/4) 0;
&.is-focused {
color: $blue;
}
}
input, textarea {
@extend %t-copy-base;
@include transition(all $tmg-f2 ease-in-out 0s);
height: 100%;
width: 100%;
padding: ($baseline/2);
// CASE: long length
&.long {
width: 100%;
}
// CASE: short length
&.short {
width: 25%;
}
}
// CASE: specific release + due times/dates
.start-date,
.start-time,
.due-date,
.due-time {
width: ($baseline*7);
}
.tip {
@extend %t-copy-sub1;
@include transition(color, 0.15s, ease-in-out);
display: block;
margin-top: ($baseline/4);
color: $gray-l2;
}
.tip-warning {
color: $gray-d2;
}
}
// CASE: type-based input
.field-text {
// TODO: refactor the _forms.scss partial to allow for this area to inherit from it
label, input, textarea {
display: block;
}
}
// CASE: select input
.field-select {
.label, .input {
display: inline-block;
vertical-align: middle;
}
.label {
@include margin-right($baseline/2);
}
.input {
width: 100%;
}
// CASE: checkbox input
.field-checkbox {
.label, label {
margin-bottom: 0;
}
}
}
}
// UI: grading section
.edit-settings-grading {
.grading-type {
margin-bottom: $baseline;
}
}
// UI: staff lock section
.edit-staff-lock {
.checkbox-cosmetic .input-checkbox {
@extend %cont-text-sr;
// CASE: unchecked
~ .tip-warning {
display: block;
}
// CASE: checked
&:checked {
~ .tip-warning {
display: none;
}
}
}
// needed to override poorly scoped margin-bottom on any label element in a view (from _forms.scss)
.checkbox-cosmetic .label {
margin-bottom: 0;
}
}
}
} }
...@@ -150,42 +150,50 @@ ...@@ -150,42 +150,50 @@
// ==================== // ====================
// UI: xblocks - calls-to-action .wrapper-xblock {
.wrapper-xblock .header-actions {
.actions-list { // UI: xblocks - calls-to-action
.header-actions .actions-list {
@extend %actions-list; @extend %actions-list;
} }
}
// UI: xblock is collapsible // CASE: xblock is collapsible
.wrapper-xblock.is-collapsible, &.is-collapsible,
.wrapper-xblock.xblock-type-container { &.xblock-type-container {
.icon { .icon {
font-style: normal; font-style: normal;
} }
.expand-collapse { .expand-collapse {
@extend %expand-collapse; @extend %expand-collapse;
margin: 0 ($baseline/4); margin: 0 ($baseline/4);
height: ($baseline*1.25); height: ($baseline*1.25);
width: $baseline; width: $baseline;
&:focus { &:focus {
outline: 0; outline: 0;
}
} }
}
.action-view { .action-view {
.action-button {
transition: none;
}
.action-button { .action-button-text {
transition: none; padding-right: ($baseline/5);
padding-left: 0;
}
} }
}
// CASE: xblock has specific visibility set
&.has-visibility-set {
.action-button-text { .action-visibility .visibility-button.visibility-button { // needed to cascade in front of overscoped header-actions CSS rule
padding-right: ($baseline/5); color: $color-visibility-set;
padding-left: 0;
} }
} }
} }
......
...@@ -6,7 +6,20 @@ ...@@ -6,7 +6,20 @@
// ==================== // ====================
// view-specific utilities
// --------------------
%status-value-base {
@extend %t-title7;
@extend %t-strong;
}
%status-value-sub1 {
@extend %t-title8;
display: block;
}
// UI: container page view // UI: container page view
// --------------------
.view-container { .view-container {
@extend %two-col-1; @extend %two-col-1;
...@@ -102,6 +115,7 @@ ...@@ -102,6 +115,7 @@
@extend %t-title8; @extend %t-title8;
} }
// UI: publishing details/summary
.bit-publishing { .bit-publishing {
@extend %bar-module; @extend %bar-module;
...@@ -159,19 +173,18 @@ ...@@ -159,19 +173,18 @@
.wrapper-release { .wrapper-release {
.release-date { .release-date {
@extend %t-strong; @extend %status-value-base;
} }
.release-with { .release-with {
@extend %t-title8; @extend %status-value-sub1;
display: block;
} }
} }
.wrapper-visibility { .wrapper-visibility {
.copy { .copy {
@extend %t-strong; @extend %status-value-base;
margin-bottom: ($baseline/10); margin-bottom: ($baseline/10);
} }
...@@ -181,15 +194,23 @@ ...@@ -181,15 +194,23 @@
} }
.inherited-from { .inherited-from {
@extend %t-title8; @extend %status-value-sub1;
display: block;
} }
// UI: note about specific access
.note-visibility {
@extend %status-value-sub1;
.icon {
@include margin-right($baseline/4);
}
}
} }
.wrapper-pub-actions { .wrapper-pub-actions {
padding: ($baseline*0.75); border-top: 1px solid $gray-l4;
margin-top: ($baseline/2);
padding: $baseline ($baseline*0.75) ($baseline*0.75) ($baseline*0.75);
.action-publish { .action-publish {
@extend %btn-primary-blue; @extend %btn-primary-blue;
...@@ -209,7 +230,6 @@ ...@@ -209,7 +230,6 @@
} }
} }
} }
} }
// versioning widget // versioning widget
...@@ -244,8 +264,7 @@ ...@@ -244,8 +264,7 @@
.wrapper-unit-id, .wrapper-library-id { .wrapper-unit-id, .wrapper-library-id {
.unit-id-value, .library-id-value { .unit-id-value, .library-id-value {
@extend %cont-text-wrap; @extend %status-value-base;
@extend %t-copy-sub1;
display: inline-block; display: inline-block;
width: 100%; width: 100%;
} }
...@@ -308,5 +327,3 @@ ...@@ -308,5 +327,3 @@
} }
} }
} }
...@@ -86,6 +86,9 @@ import json ...@@ -86,6 +86,9 @@ import json
</div> </div>
<div id="page-prompt"></div> <div id="page-prompt"></div>
<%block name="modal_placeholder"></%block>
<%block name="jsextra"></%block> <%block name="jsextra"></%block>
<script type="text/javascript"> <script type="text/javascript">
require(['js/factories/common_deps'], function () { require(['js/factories/common_deps'], function () {
......
...@@ -144,3 +144,8 @@ from django.utils.translation import ugettext as _ ...@@ -144,3 +144,8 @@ from django.utils.translation import ugettext as _
</div> </div>
</div> </div>
</%block> </%block>
<!-- NOTE: remove this HTML if you want to not see the fake visibility modal -->
<%block name="modal_placeholder">
<%include file="ux/reference/modal_access-component.html" />
</%block>
...@@ -66,7 +66,7 @@ var visibleToStaffOnly = visibilityState === 'staff_only'; ...@@ -66,7 +66,7 @@ var visibleToStaffOnly = visibilityState === 'staff_only';
<% } %> <% } %>
</h5> </h5>
<% if (visibleToStaffOnly) { %> <% if (visibleToStaffOnly) { %>
<p class="copy"> <p class="visbility-copy copy">
<%= gettext("Staff Only") %> <%= gettext("Staff Only") %>
<% if (!hasExplicitStaffLock) { %> <% if (!hasExplicitStaffLock) { %>
<span class="inherited-from"> <span class="inherited-from">
...@@ -75,10 +75,18 @@ var visibleToStaffOnly = visibilityState === 'staff_only'; ...@@ -75,10 +75,18 @@ var visibleToStaffOnly = visibilityState === 'staff_only';
<% } %> <% } %>
</p> </p>
<% } else { %> <% } else { %>
<p class="copy"><%= gettext("Staff and Students") %></p> <p class="visbility-copy copy"><%= gettext("Staff and Students") %></p>
<% } %> <% } %>
<p class="action-inline">
<a href="" class="action-staff-lock" role="button" aria-pressed="<%= hasExplicitStaffLock %>"> <!-- NOTE: @andyarmstrong, here's the new copy we're adding to the visibility summary UI to make sure we're as accurate as we can be at the final state of the unit/container's visibility -->
<p class="note-visibility">
<i class="icon icon-eye-open"></i>
<span class="note-copy"><%= gettext("Some content in this unit is only visible to particular groups") %></span>
</p>
<ul class="actions-inline">
<li class="action-inline">
<a href="" class="action-staff-lock" role="button" aria-pressed="<%= hasExplicitStaffLock %>">
<% if (hasExplicitStaffLock) { %> <% if (hasExplicitStaffLock) { %>
<i class="icon fa fa-check-square-o"></i> <i class="icon fa fa-check-square-o"></i>
<% } else { %> <% } else { %>
...@@ -86,7 +94,8 @@ var visibleToStaffOnly = visibilityState === 'staff_only'; ...@@ -86,7 +94,8 @@ var visibleToStaffOnly = visibilityState === 'staff_only';
<% } %> <% } %>
<%= gettext('Hide from students') %> <%= gettext('Hide from students') %>
</a> </a>
</p> </li>
</ul>
</div> </div>
<div class="wrapper-pub-actions bar-mod-actions"> <div class="wrapper-pub-actions bar-mod-actions">
......
...@@ -38,7 +38,8 @@ messages = json.dumps(xblock.validate().to_json()) ...@@ -38,7 +38,8 @@ messages = json.dumps(xblock.validate().to_json())
<div class="studio-xblock-wrapper" data-locator="${xblock.location | h}" data-course-key="${xblock.location.course_key | h}"> <div class="studio-xblock-wrapper" data-locator="${xblock.location | h}" data-course-key="${xblock.location.course_key | h}">
% endif % endif
<section class="wrapper-xblock ${section_class} ${collapsible_class}"> <!-- NOTE: @andyarmstrong, in order to style the case when an access level is set, we need to add a class to each xblock's wrapper. How does .has-visiblity-set sound? -->
<section class="wrapper-xblock ${section_class} ${collapsible_class} has-visibility-set">
% endif % endif
<header class="xblock-header xblock-header-${xblock.category}"> <header class="xblock-header xblock-header-${xblock.category}">
...@@ -76,6 +77,19 @@ messages = json.dumps(xblock.validate().to_json()) ...@@ -76,6 +77,19 @@ messages = json.dumps(xblock.validate().to_json())
<span class="sr">${_("Delete")}</span> <span class="sr">${_("Delete")}</span>
</a> </a>
</li> </li>
<!-- NOTE: @andyarmstrong, here's a static version of the new access control we're adding. Remember we wanted to update the tooltip if particular groups were set on a component -->
<li class="action-item action-visibility">
<a href="#" data-tooltip="${_("Visibility Settings")}" class="visibility-button action-button">
<i class="icon-eye-open"></i>
<span class="sr">${_("Visibility")}</span>
</a>
</li>
<li class="action-item action-duplicate">
<a href="#" data-tooltip="${_("Duplicate")}" class="duplicate-button action-button">
<i class="icon fa fa-copy"></i>
<span class="sr">${_("Duplicate")}</span>
</a>
</li>
% if is_reorderable: % if is_reorderable:
<li class="action-item action-drag"> <li class="action-item action-drag">
<span data-tooltip="${_('Drag to reorder')}" class="drag-handle action"></span> <span data-tooltip="${_('Drag to reorder')}" class="drag-handle action"></span>
......
<div class="wrapper wrapper-modal-window wrapper-modal-window-edit-xblock" aria-describedby="modal-window-description" aria-labelledby="modal-window-title" aria-hidden="" role="dialog">
<div class="modal-window-overlay"></div>
<div class="modal-window confirm modal-med modal-type-html modal-editor" style="top: 50px; left: 400px;">
<div class="edit-xblock-modal">
<div class="modal-header">
<h2 class="title modal-window-title">Editing visibility for: [Component Name]</h2>
</div>
<div class="modal-content">
<div class="xblock-editor" data-locator="i4x://TestU/cohorts001/chapter/748152225449412a846bc24811a5621c" data-course-key="">
<div class="xblock xblock-visibility_view">
<div class="modal-section visibility-summary">
<div class="summary-message summary-message-warning visibility-summary-message">
<i class="icon icon-warning-sign"></i>
<p class="copy">This component is contained in a unit that is hidden from students. Component visibility settings are overridden by the unit visibility settings.</p>
</div>
<!-- NOTE: use when no group configuration has been set -->
<div class="is-not-configured has-actions">
<h4 class="title">You have not set up any groups</h4>
<div class="copy">
<p>Groups are a way for you to organize content in your course with a particular student experience in mind. They are commonly used to facilitate content and pedagogical experiments as well as to provide different tracks of content.</p>
</div>
<div class="actions">
<a href="" class="action action-primary action-settings">Manage groups in this course</a>
</div>
</div>
</div>
<form class="visibility-controls-form" method="post" action="">
<div class="modal-section visibility-controls">
<h3 class="modal-section-title">Set visibility to:</h3>
<div class="modal-section-content">
<section class="visibility-controls-primary">
<ul class="list-fields list-radio">
<li class="field field-radio field-visibility-level">
<input type="radio" id="visibility-level-all" name="visibility-level" value="" class="input input-radio visibility-level-all" />
<label for="visibility-level-all" class="label">All Students and Staff</label>
</li>
<li class="field field-radio field-visibility-level">
<input type="radio" id="visibility-level-specific" name="visibility-level" value="" class="input input-radio visibility-level-specific" checked="checked" />
<label for="visibility-level-specific" class="label">Specific Groups</label>
</li>
</ul>
</section>
<!-- NOTE: @andyarmstrong, if you need this wrapper to show and hide, great. If not, please remove it from the DOM -->
<div class="wrapper-visibility-specific">
<section class="visibility-controls-secondary">
<div class="visibility-controls-group">
<h4 class="visibility-controls-title modal-subsection-title sr">Content Groups</h4>
<ul class="list-fields list-checkbox">
<li class="field field-checkbox field-visibility-content-group">
<input type="checkbox" id="visibility-content-group-NAME1" name="visibility-content-group" value="" class="input input-checkbox visibility-content-group-NAME1" />
<label for="visibility-content-group-NAME1" class="label">Content Group NAME 1</label>
</li>
<li class="field field-checkbox field-visibility-content-group">
<input type="checkbox" id="visibility-content-group-NAME2" name="visibility-content-group" value="" class="input input-checkbox visibility-content-group-NAME2" />
<label for="visibility-content-group-NAME2" class="label">Content Group NAME 2</label>
</li>
<li class="field field-checkbox field-visibility-content-group">
<input type="checkbox" id="visibility-content-group-NAME3" name="visibility-content-group" value="" class="input input-checkbox visibility-content-group-NAME3" />
<label for="visibility-content-group-NAME3" class="label">Content Group NAME 3</label>
</li>
<li class="field field-checkbox field-visibility-content-group">
<input type="checkbox" id="visibility-content-group-NAME4" name="visibility-content-group" value="" class="input input-checkbox visibility-content-group-NAME4" />
<label for="visibility-content-group-NAME4" class="label">Content Group NAME 4</label>
</li>
<!-- NOTE: @andyarmstrong, here's an example of how we would treat a group that was deleted/removed - we need a .was removed class and an additional UI element called a .note -->
<li class="field field-checkbox field-visibility-content-group was-removed">
<input type="checkbox" id="visibility-content-group-deleted1" name="visibility-content-group" value="" class="input input-checkbox visibility-content-group-deleted" checked="checked" />
<label for="visibility-content-group-deleted1" class="label">
Deleted Content Group
</label>
<span class="note">The selected group no longer exists. Choose another group or make the component visible to All Students and Staff</span>
</li>
<!-- NOTE: @andyarmstrong, here's an example of how we would treat a group that was deleted/removed - we need a .was removed class and an additional UI element called a .note -->
<li class="field field-checkbox field-visibility-content-group was-removed">
<input type="checkbox" id="visibility-content-group-deleted1" name="visibility-content-group" value="" class="input input-checkbox visibility-content-group-deleted" checked="checked" />
<label for="visibility-content-group-deleted1" class="label">
Deleted Content Group
</label>
<span class="note">The selected group no longer exists. Choose another group or make the component visible to All Students and Staff</span>
</li>
</ul>
</div>
</section>
</div>
</div>
</div>
</form>
</div><!-- .xblock -->
</div><!-- .xblock-editor -->
</div><!-- .modal-content -->
<div class="modal-actions">
<h3 class="sr">Actions</h3>
<ul>
<li class="action-item">
<a href="#" class="button action-primary action-save">Save</a>
</li>
<li class="action-item">
<a href="#" class="button action-cancel">Cancel</a>
</li>
</ul>
</div>
</div><!-- .xblock-visibility-modal -->
</div><!-- .modal-window -->
</div><!-- .wrapper-modal-window -->
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment