Commit d569c559 by Don Mitchell

Merge branch 'feature/btalbot/studio-softlanding' of github.com:MITx/mitx into…

Merge branch 'feature/btalbot/studio-softlanding' of github.com:MITx/mitx into feature/btalbot/studio-softlanding

Conflicts:
	cms/djangoapps/contentstore/views.py
	cms/static/js/views/settings/main_settings_view.js
	cms/templates/index.html
	cms/templates/settings.html
parents 40668133 540710f5
......@@ -94,6 +94,8 @@ def login_page(request):
'forgot_password_link': "//{base}/#forgot-password-modal".format(base=settings.LMS_BASE),
})
def howitworks(request):
return render_to_response('howitworks.html', {})
# ==== Views for any logged-in user ==================================
......@@ -730,8 +732,6 @@ def clone_item(request):
#@login_required
#@ensure_csrf_cookie
def upload_asset(request, org, course, coursename):
'''
cdodge: this method allows for POST uploading of files into the course asset library, which will
......@@ -796,8 +796,6 @@ def upload_asset(request, org, course, coursename):
'''
This view will return all CMS users who are editors for the specified course
'''
@login_required
@ensure_csrf_cookie
def manage_users(request, location):
......@@ -819,7 +817,7 @@ def manage_users(request, location):
})
def create_json_response(errmsg=None):
def create_json_response(errmsg = None):
if errmsg is not None:
resp = HttpResponse(json.dumps({'Status': 'Failed', 'ErrMsg': errmsg}))
else:
......@@ -831,8 +829,6 @@ def create_json_response(errmsg=None):
This POST-back view will add a user - specified by email - to the list of editors for
the specified course
'''
@expect_json
@login_required
@ensure_csrf_cookie
......@@ -865,8 +861,6 @@ def add_user(request, location):
This POST-back view will remove a user - specified by email - from the list of editors for
the specified course
'''
@expect_json
@login_required
@ensure_csrf_cookie
......@@ -1124,8 +1118,31 @@ def get_course_settings(request, org, course, name):
course_details = CourseDetails.fetch(location)
return render_to_response('settings.html', {
'active_tab': 'settings',
'context_course': course_module,
'course_location' : location,
'course_details' : json.dumps(course_details, cls=CourseSettingsEncoder)
})
@login_required
@ensure_csrf_cookie
def course_config_graders_page(request, org, course, name):
"""
Send models and views as well as html for editing the course settings to the client.
org, course, name: Attributes of the Location for the item to edit
"""
location = ['i4x', org, course, 'course', name]
# check that logged in user has permissions to this item
if not has_access(request.user, location):
raise PermissionDenied()
course_module = modulestore().get_item(location)
course_details = CourseGradingModel.fetch(location)
return render_to_response('settings_graders.html', {
'context_course': course_module,
'course_location' : location,
'course_details': json.dumps(course_details, cls=CourseSettingsEncoder)
})
......
<li class="input input-existing multi course-grading-assignment-list-item">
<div class="row row-col2">
<label for="course-grading-assignment-name">Assignment Type Name:</label>
<div class="field">
<div class="input course-grading-assignment-name">
<input type="text" class="long"
id="course-grading-assignment-name" value="<%= model.get('type') %>">
<span class="tip tip-stacked">e.g. Homework, Labs, Midterm Exams, Final Exam</span>
</div>
</div>
<li class="field-group course-grading-assignment-list-item">
<div class="field text" id="field-course-grading-assignment-name">
<label for="course-grading-assignment-name">Assignment Type Name</label>
<input type="text" class="long" id="course-grading-assignment-name" value="<%= model.get('type') %>" />
<span class="tip tip-stacked">e.g. Homework, Midterm Exams</span>
</div>
<div class="row row-col2">
<div class="field text" id="field-course-grading-assignment-shortname">
<label for="course-grading-shortname">Abbreviation:</label>
<div class="field">
<div class="input course-grading-shortname">
<input type="text" class="short"
id="course-grading-assignment-shortname"
value="<%= model.get('short_label') %>">
<span class="tip tip-inline">e.g. HW, Midterm, Final</span>
</div>
</div>
<input type="text" class="short" id="course-grading-assignment-shortname" value="<%= model.get('short_label') %>" />
<span class="tip tip-inline">e.g. HW, Midterm</span>
</div>
<div class="row row-col2">
<label for="course-grading-gradeweight">Weight of Total
Grade:</label>
<div class="field">
<div class="input course-grading-gradeweight">
<input type="text" class="short"
id="course-grading-assignment-gradeweight"
value = "<%= model.get('weight') %>">
<div class="field text" id="field-course-grading-assignment-gradeweight">
<label for="course-grading-gradeweight">Weight of Total Grade</label>
<input type="text" class="short" id="course-grading-assignment-gradeweight" value = "<%= model.get('weight') %>" />
<span class="tip tip-inline">e.g. 25%</span>
</div>
</div>
</div>
<div class="row row-col2">
<label for="course-grading-assignment-totalassignments">Total
Number:</label>
<div class="field">
<div class="input course-grading-totalassignments">
<input type="text" class="short"
id="course-grading-assignment-totalassignments"
value = "<%= model.get('min_count') %>">
<div class="field text" id="field-course-grading-assignment-totalassignments">
<label for="course-grading-gradeweight">Total
Number</label>
<input type="text" class="short" id="course-grading-assignment-totalassignments" value = "<%= model.get('min_count') %>" />
<span class="tip tip-inline">total exercises assigned</span>
</div>
</div>
</div>
<div class="row row-col2">
<label for="course-grading-assignment-droppable">Number of
Droppable:</label>
<div class="field">
<div class="input course-grading-droppable">
<input type="text" class="short"
id="course-grading-assignment-droppable"
value = "<%= model.get('drop_count') %>">
<div class="field text" id="field-course-grading-assignment-droppable">
<label for="course-grading-gradeweight">Number of
Droppable</label>
<input type="text" class="short" id="course-grading-assignment-droppable" value = "<%= model.get('drop_count') %>" />
<span class="tip tip-inline">total exercises that won't be graded</span>
</div>
<div class="actions">
<a href="#" class="button delete-button standard remove-item remove-grading-data"><span class="delete-icon"></span>Delete</a>
</div>
</div>
<a href="#" class="delete-button standard remove-item remove-grading-data"><span class="delete-icon"></span>Delete</a>
</li>
......@@ -31,7 +31,7 @@ $(document).ready(function() {
$modal.bind('click', hideModal);
$modalCover.bind('click', hideModal);
$('.assets .upload-button').bind('click', showUploadModal);
$('.uploads .upload-button').bind('click', showUploadModal);
$('.upload-modal .close-button').bind('click', hideModal);
$body.on('click', '.embeddable-xml-input', function(){ $(this).select(); });
......@@ -39,6 +39,41 @@ $(document).ready(function() {
$('.unit .item-actions .delete-button').bind('click', deleteUnit);
$('.new-unit-item').bind('click', createNewUnit);
// nav-related
$('body').addClass('js');
$('.nav-dropdown .nav-item .title').click(function(e){
$subnav = $(this).parent().find('.wrapper-nav-sub');
$title = $(this).parent().find('.title');
e.preventDefault();
if ($subnav.hasClass('is-shown')) {
$subnav.removeClass('is-shown');
$title.removeClass('is-selected');
}
else {
$('.nav-dropdown .nav-item .title').removeClass('is-selected');
$('.nav-dropdown .nav-item .wrapper-nav-sub').removeClass('is-shown');
$title.addClass('is-selected');
$subnav.addClass('is-shown');
}
});
// general link management - new window/tab
$('a[rel="external"]').attr('title','This link will open in a new browser window/tab').click(function(e) {
window.open($(this).attr('href'));
e.preventDefault();
});
// general link management - lean modal window
$('a[rel="modal"]').attr('title','This link will open in a modal window').leanModal({overlay : 0.50, closeButton: '.action-modal-close' });
$('.action-modal-close').click(function(e){
(e).preventDefault();
});
// toggling overview section details
$(function(){
if($('.courseware-section').length > 0) {
......
......@@ -61,19 +61,17 @@ CMS.Models.Settings.CourseDetails = Backbone.Model.extend({
url: function() {
var location = this.get('location');
return '/' + location.get('org') + "/" + location.get('course') + '/settings/' + location.get('name') + '/section/details';
return '/' + location.get('org') + "/" + location.get('course') + '/settings-details/' + location.get('name') + '/section/details';
},
_videokey_illegal_chars : /[^a-zA-Z0-9_-]/g,
save_videosource: function(newsource) {
// newsource either is <video youtube="speed:key, *"/> or just the "speed:key, *" string
// returns the videosource for the preview which iss the key whose speed is closest to 1
if (_.isEmpty(newsource) && !_.isEmpty(this.get('intro_video'))) this.save({'intro_video': null},
{ error : CMS.ServerError});
if (_.isEmpty(newsource) && !_.isEmpty(this.get('intro_video'))) this.set({'intro_video': null});
// TODO remove all whitespace w/in string
else {
if (this.get('intro_video') !== newsource) this.save('intro_video', newsource,
{ error : CMS.ServerError});
if (this.get('intro_video') !== newsource) this.set('intro_video', newsource);
}
return this.videosourceSample();
......
......@@ -13,7 +13,8 @@ CMS.Models.Settings.CourseGradingPolicy = Backbone.Model.extend({
}
if (attributes['graders']) {
var graderCollection;
if (this.has('graders')) {
// interesting race condition: if {parse:true} when newing, then parse called before .attributes created
if (this.attributes && this.has('graders')) {
graderCollection = this.get('graders');
graderCollection.reset(attributes.graders);
}
......@@ -27,7 +28,7 @@ CMS.Models.Settings.CourseGradingPolicy = Backbone.Model.extend({
},
url : function() {
var location = this.get('course_location');
return '/' + location.get('org') + "/" + location.get('course') + '/settings/' + location.get('name') + '/section/grading';
return '/' + location.get('org') + "/" + location.get('course') + '/settings-details/' + location.get('name') + '/section/grading';
},
gracePeriodToDate : function() {
var newDate = new Date();
......@@ -119,7 +120,7 @@ CMS.Models.Settings.CourseGraderCollection = Backbone.Collection.extend({
model : CMS.Models.Settings.CourseGrader,
course_location : null, // must be set to a Location object
url : function() {
return '/' + this.course_location.get('org') + "/" + this.course_location.get('course') + '/grades/' + this.course_location.get('name') + '/';
return '/' + this.course_location.get('org') + "/" + this.course_location.get('course') + '/settings-grading/' + this.course_location.get('name') + '/';
},
sumWeights : function() {
return this.reduce(function(subtotal, grader) { return subtotal + grader.get('weight'); }, 0);
......
......@@ -3,7 +3,6 @@ CMS.Models.Settings.CourseSettings = Backbone.Model.extend({
// a container for the models representing the n possible tabbed states
defaults: {
courseLocation: null,
// NOTE: keep these sync'd w/ the data-section names in settings-page-menu
details: null,
faculty: null,
grading: null,
......
CMS.Views.ValidatingView = Backbone.View.extend({
// Intended as an abstract class which catches validation errors on the model and
// decorates the fields. Needs wiring per class, but this initialization shows how
// either have your init call this one or copy the contents
initialize : function() {
this.model.on('error', this.handleValidationError, this);
this.selectorToField = _.invert(this.fieldToSelectorMap);
},
errorTemplate : _.template('<span class="message-error"><%= message %></span>'),
events : {
"blur input" : "clearValidationErrors",
"blur textarea" : "clearValidationErrors"
},
fieldToSelectorMap : {
// Your subclass must populate this w/ all of the model keys and dom selectors
// which may be the subjects of validation errors
},
_cacheValidationErrors : [],
handleValidationError : function(model, error) {
// error triggered either by validation or server error
// error is object w/ fields and error strings
for (var field in error) {
var ele = this.$el.find('#' + this.fieldToSelectorMap[field]);
if (ele.length === 0) {
// check if it might a server error: note a typo in the field name
// or failure to put in a map may cause this to muffle validation errors
if (_.has(error, 'error') && _.has(error, 'responseText')) {
CMS.ServerError(model, error);
return;
}
else continue;
}
this._cacheValidationErrors.push(ele);
if ($(ele).is('div')) {
// put error on the contained inputs
$(ele).find('input, textarea').addClass('error');
}
else $(ele).addClass('error');
$(ele).parent().append(this.errorTemplate({message : error[field]}));
}
},
clearValidationErrors : function() {
// error is object w/ fields and error strings
while (this._cacheValidationErrors.length > 0) {
var ele = this._cacheValidationErrors.pop();
if ($(ele).is('div')) {
// put error on the contained inputs
$(ele).find('input, textarea').removeClass('error');
}
else $(ele).removeClass('error');
$(ele).nextAll('.message-error').remove();
}
},
saveIfChanged : function(event) {
// returns true if the value changed and was thus sent to server
var field = this.selectorToField[event.currentTarget.id];
var currentVal = this.model.get(field);
var newVal = $(event.currentTarget).val();
this.clearValidationErrors(); // curr = new if user reverts manually
if (currentVal != newVal) {
this.model.save(field, newVal);
return true;
}
else return false;
},
// these should perhaps go into a superclass but lack of event hash inheritance demotivates me
inputFocus : function(event) {
$("label[for='" + event.currentTarget.id + "']").addClass("is-focused");
},
inputUnfocus : function(event) {
$("label[for='" + event.currentTarget.id + "']").removeClass("is-focused");
}
});
// Studio - Sign In/Up
// ====================
body.signup, body.signin {
.wrapper-content {
margin: 0;
padding: 0 $baseline;
position: relative;
width: 100%;
}
.content {
@include clearfix();
@include font-size(16);
max-width: $fg-max-width;
min-width: $fg-min-width;
width: flex-grid(12);
margin: 0 auto;
color: $gray-d2;
header {
position: relative;
margin-bottom: $baseline;
border-bottom: 1px solid $gray-l4;
padding-bottom: ($baseline/2);
h1 {
@include font-size(32);
margin: 0;
padding: 0;
font-weight: 600;
}
.action {
@include font-size(13);
position: absolute;
right: 0;
top: 40%;
}
}
.introduction {
@include font-size(14);
margin: 0 0 $baseline 0;
}
}
.content-primary, .content-supplementary {
@include box-sizing(border-box);
float: left;
}
.content-primary {
width: flex-grid(8, 12);
margin-right: flex-gutter();
form {
@include box-sizing(border-box);
@include box-shadow(0 1px 2px $shadow-l1);
@include border-radius(2px);
width: 100%;
border: 1px solid $gray-l2;
padding: $baseline ($baseline*1.5);
background: $white;
.form-actions {
margin-top: $baseline;
.action-primary {
@include blue-button;
@include transition(all .15s);
@include font-size(15);
display:block;
width: 100%;
padding: ($baseline*0.75) ($baseline/2);
font-weight: 600;
text-transform: uppercase;
}
}
.list-input {
margin: 0;
padding: 0;
list-style: none;
.field {
margin: 0 0 ($baseline*0.75) 0;
&:last-child {
margin-bottom: 0;
}
&.required {
label {
font-weight: 600;
}
label:after {
margin-left: ($baseline/4);
content: "*";
}
}
label, input, textarea {
display: block;
}
label {
@include font-size(14);
@include transition(color, 0.15s, ease-in-out);
margin: 0 0 ($baseline/4) 0;
&.is-focused {
color: $blue;
}
}
input, textarea {
@include font-size(16);
height: 100%;
width: 100%;
padding: ($baseline/2);
&.long {
width: 100%;
}
&.short {
width: 25%;
}
::-webkit-input-placeholder {
color: $gray-l4;
}
:-moz-placeholder {
color: $gray-l3;
}
::-moz-placeholder {
color: $gray-l3;
}
:-ms-input-placeholder {
color: $gray-l3;
}
}
textarea.long {
height: ($baseline*5);
}
input[type="checkbox"] {
display: inline-block;
margin-right: ($baseline/4);
width: auto;
height: auto;
& + label {
display: inline-block;
}
}
.tip {
@include font-size(13);
display: block;
margin-top: ($baseline/4);
color: $gray-l3;
}
}
.field-group {
@include clearfix();
margin: 0 0 ($baseline/2) 0;
.field {
display: block;
width: 47%;
border-bottom: none;
margin: 0 $baseline 0 0;
padding-bottom: 0;
&:nth-child(odd) {
float: left;
}
&:nth-child(even) {
float: right;
margin-right: 0;
}
input, textarea {
width: 100%;
}
}
}
}
}
}
.content-supplementary {
width: flex-grid(4, 12);
.bit {
@include font-size(13);
margin: 0 0 $baseline 0;
border-bottom: 1px solid $gray-l4;
padding: 0 0 $baseline 0;
color: $gray-l1;
&:last-child {
margin-bottom: 0;
border: none;
padding-bottom: 0;
}
h3 {
@include font-size(14);
margin: 0 0 ($baseline/4) 0;
color: $gray-d2;
font-weight: 600;
}
}
}
}
.signup {
}
.signin {
#field-password {
position: relative;
.action-forgotpassword {
@include font-size(13);
position: absolute;
top: 0;
right: 0;
}
}
}
// ====================
// messages
.message {
@include font-size(14);
display: block;
}
.message-status {
display: none;
@include border-top-radius(2px);
@include box-sizing(border-box);
border-bottom: 2px solid $yellow-d2;
margin: 0 0 $baseline 0;
padding: ($baseline/2) $baseline;
font-weight: 500;
background: $yellow-d1;
color: $white;
.ss-icon {
position: relative;
top: 3px;
@include font-size(16);
display: inline-block;
margin-right: ($baseline/2);
}
.text {
display: inline-block;
}
&.error {
border-color: shade($red, 50%);
background: tint($red, 20%);
}
&.is-shown {
display: block;
}
}
.assets {
.uploads {
input.asset-search-input {
float: left;
width: 260px;
......
// -------------------------------------
//
// Universal
//
// -------------------------------------
// studio base styling
// ====================
// basic reset
html {
font-size: 62.5%;
}
body {
@include font-size(16);
min-width: 980px;
background: rgb(240, 241, 245);
font-size: 16px;
background: $gray-l5;
line-height: 1.6;
color: $baseFontColor;
}
body,
input {
body, input {
font-family: 'Open Sans', sans-serif;
}
......@@ -28,10 +29,8 @@ a {
}
h1 {
float: left;
font-size: 28px;
@include font-size(28);
font-weight: 300;
margin: 24px 6px;
}
.waiting {
......@@ -42,6 +41,128 @@ h1 {
margin-bottom: 30px;
}
.wrapper {
@include clearfix();
@include box-sizing(border-box);
width: 100%;
}
// ====================
// layout - basic
.wrapper-content {
margin: 0;
padding: 0 $baseline;
position: relative;
}
.content {
@include clearfix();
@include font-size(16);
max-width: $fg-max-width;
min-width: $fg-min-width;
width: flex-grid(12);
margin: 0 auto;
color: $gray-d2;
header {
position: relative;
margin-bottom: $baseline;
border-bottom: 1px solid $gray-l4;
padding-bottom: ($baseline/2);
.title-sub {
@include font-size(14);
display: block;
margin: 0;
color: $gray-l2;
}
.title, .title-1 {
@include font-size(32);
margin: 0;
padding: 0;
font-weight: 600;
color: $gray-d3;
}
}
.introduction {
@include font-size(14);
margin: 0 0 $baseline 0;
}
}
.content-primary, .content-supplementary {
@include box-sizing(border-box);
}
.content-primary {
.title-1, .title-2, .title-3, .title-4, .title-5, .title-5 {
color: $gray-d3;
}
.title-1 {
}
.title-2 {
@include font-size(24);
margin: 0 0 ($baseline/2) 0;
font-weight: 600;
}
.title-3 {
@include font-size(16);
margin: 0 0 ($baseline/4) 0;
font-weight: 500;
}
.title-4 {
}
.title-5 {
}
}
.content-supplementary {
.bit {
@include font-size(13);
margin: 0 0 $baseline 0;
border-bottom: 1px solid $gray-l4;
padding: 0 0 $baseline 0;
color: $gray-l1;
&:last-child {
margin-bottom: 0;
border: none;
padding-bottom: 0;
}
h3 {
@include font-size(14);
margin: 0 0 ($baseline/4) 0;
color: $gray-d2;
font-weight: 600;
}
p {
margin: 0 0 $baseline 0;
&:last-child {
margin-bottom: 0;
}
}
}
}
// ====================
// layout - grandfathered
.main-wrapper {
position: relative;
margin: 0 40px;
......@@ -70,11 +191,9 @@ h1 {
float: right;
}
footer {
clear: both;
height: 100px;
}
// ====================
// forms
input[type="text"],
input[type="email"],
input[type="password"],
......@@ -103,6 +222,7 @@ textarea.text {
}
}
// forms - specific
input.search {
padding: 6px 15px 8px 30px;
@include box-sizing(border-box);
......@@ -147,6 +267,21 @@ code {
font-family: Monaco, monospace;
}
// ====================
// UI - chrome
.window {
@include clearfix();
@include border-radius(3px);
@include box-shadow(0 1px 1px $shadow-l1);
margin-bottom: $baseline;
border: 1px solid $gray-l2;
background: $white;
}
// ====================
// UI - actions
.new-unit-item,
.new-subsection-item,
.new-policy-item {
......@@ -177,6 +312,13 @@ code {
}
}
// ====================
// misc
hr.divide {
@include text-sr();
}
.item-details {
float: left;
padding: 10px 0;
......@@ -189,11 +331,11 @@ code {
}
.window {
margin-bottom: 20px;
border: 1px solid $mediumGrey;
border-radius: 3px;
background: #fff;
@include box-shadow(0 1px 1px rgba(0, 0, 0, 0.1));
// @include border-radius(3px);
// @include box-shadow(0 1px 1px $shadow-l1);
// margin-bottom: $baseline;
// border: 1px solid $gray-l2;
// background: $white;
.window-contents {
padding: 20px;
......@@ -236,34 +378,9 @@ code {
}
}
body.hide-wip {
.wip, .wip-box {
display: none !important;
}
}
body.show-wip {
.wip {
outline: 1px solid #f00 !important;
position: relative;
}
// ====================
.wip-box {
@extend .wip;
&:after {
content: "WIP";
font-size: 8px;
padding: 2px;
background: #f00;
color: #fff;
@include position(absolute, 0px 0px 0 0);
}
}
}
.waiting {
}
// system notifications
.toast-notification {
display: none;
position: fixed;
......@@ -418,3 +535,37 @@ body.show-wip {
color: rgba(0, 0, 0, 0.85);
}
}
// ====================
// basic utility
.sr {
@include text-sr();
}
.fake-link {
cursor: pointer;
}
.non-list {
list-style: none;
margin: 0;
padding: 0;
}
.wrap {
text-wrap: wrap;
white-space: pre-wrap;
white-space: -moz-pre-wrap;
word-wrap: break-word;
}
// ====================
// works in progress
body.hide-wip {
.wip-box {
display: none;
}
}
\ No newline at end of file
......@@ -28,7 +28,7 @@
}
}
&:hover {
&:hover, &.active {
@include box-shadow(0 1px 0 rgba(255, 255, 255, .3) inset, 0 1px 1px rgba(0, 0, 0, .15));
}
}
......@@ -41,7 +41,7 @@
background-color: $blue;
color: #fff;
&:hover {
&:hover, &.active {
background-color: #62aaf5;
color: #fff;
}
......
.faded-hr-divider {
@include background-image(linear-gradient(180deg, rgba(200,200,200, 0) 0%,
rgba(200,200,200, 1) 50%,
rgba(200,200,200, 0)));
height: 1px;
width: 100%;
}
.faded-hr-divider-medium {
@include background-image(linear-gradient(180deg, rgba(240,240,240, 0) 0%,
rgba(240,240,240, 1) 50%,
rgba(240,240,240, 0)));
height: 1px;
width: 100%;
}
.faded-hr-divider-light {
@include background-image(linear-gradient(180deg, rgba(255,255,255, 0) 0%,
rgba(255,255,255, 0.8) 50%,
rgba(255,255,255, 0)));
height: 1px;
width: 100%;
}
.faded-vertical-divider {
@include background-image(linear-gradient(90deg, rgba(200,200,200, 0) 0%,
rgba(200,200,200, 1) 50%,
rgba(200,200,200, 0)));
height: 100%;
width: 1px;
}
.faded-vertical-divider-light {
@include background-image(linear-gradient(90deg, rgba(255,255,255, 0) 0%,
rgba(255,255,255, 0.6) 50%,
rgba(255,255,255, 0)));
height: 100%;
width: 1px;
}
.vertical-divider {
@extend .faded-vertical-divider;
position: relative;
&::after {
@extend .faded-vertical-divider-light;
content: "";
display: block;
position: absolute;
left: 1px;
}
}
.horizontal-divider {
border: none;
@extend .faded-hr-divider;
position: relative;
&::after {
@extend .faded-hr-divider-light;
content: "";
display: block;
position: absolute;
top: 1px;
}
}
.fade-right-hr-divider {
@include background-image(linear-gradient(180deg, rgba(200,200,200, 0) 0%,
rgba(200,200,200, 1)));
border: none;
}
.fade-left-hr-divider {
@include background-image(linear-gradient(180deg, rgba(200,200,200, 1) 0%,
rgba(200,200,200, 0)));
border: none;
}
\ No newline at end of file
//studio global footer
.wrapper-footer {
margin: ($baseline*1.5) 0 $baseline 0;
padding: $baseline;
position: relative;
width: 100%;
footer.primary {
@include clearfix();
@include font-size(13);
max-width: $fg-max-width;
min-width: $fg-min-width;
width: flex-grid(12);
margin: 0 auto;
padding-top: $baseline;
border-top: 1px solid $gray-l4;
color: $gray-l2;
.colophon {
width: flex-grid(4, 12);
float: left;
margin-right: flex-gutter(2);
}
.nav-peripheral {
width: flex-grid(6, 12);
float: right;
text-align: right;
.nav-item {
display: inline-block;
margin-right: ($baseline/2);
&:last-child {
margin-right: 0;
}
}
}
a {
color: $gray-l1;
&:hover, &:active {
color: $blue;
}
}
}
}
\ No newline at end of file
......@@ -55,3 +55,15 @@
margin-top: 13px;
}
}
// lean modal alternative
#lean_overlay {
position: fixed;
z-index: 10000;
top: 0px;
left: 0px;
display: none;
height: 100%;
width: 100%;
background: $black;
}
\ No newline at end of file
......@@ -29,6 +29,7 @@
&.new-component-item {
margin-top: 20px;
background: transparent;
}
}
......
.subsection .main-wrapper {
margin: 40px;
}
.subsection .inner-wrapper {
@include clearfix();
}
.subsection-body {
padding: 32px 40px;
@include clearfix;
......
.unit .main-wrapper,
.subsection .main-wrapper {
.unit .main-wrapper {
@include clearfix();
margin: 40px;
}
......
$gw-column: 80px;
$gw-gutter: 20px;
$baseline: 20px;
// grid
$gw-column: ($baseline*3);
$gw-gutter: $baseline;
$fg-column: $gw-column;
$fg-gutter: $gw-gutter;
$fg-max-columns: 12;
$fg-max-width: 1400px;
$fg-min-width: 810px;
$fg-max-width: 1280px;
$fg-min-width: 900px;
// type
$sans-serif: 'Open Sans', $verdana;
$body-line-height: golden-ratio(.875em, 1);
$error-red: rgb(253, 87, 87);
$white: rgb(255,255,255);
// colors - new for re-org
$black: rgb(0,0,0);
$pink: rgb(182,37,104);
$error-red: rgb(253, 87, 87);
$white: rgb(255,255,255);
$gray: rgb(127,127,127);
$gray-l1: tint($gray,20%);
$gray-l2: tint($gray,40%);
$gray-l3: tint($gray,60%);
$gray-l4: tint($gray,80%);
$gray-l5: tint($gray,90%);
$gray-d1: shade($gray,20%);
$gray-d2: shade($gray,40%);
$gray-d3: shade($gray,60%);
$gray-d4: shade($gray,80%);
$blue: rgb(85, 151, 221);
$blue-l1: tint($blue,20%);
$blue-l2: tint($blue,40%);
$blue-l3: tint($blue,60%);
$blue-l4: tint($blue,80%);
$blue-l5: tint($blue,90%);
$blue-d1: shade($blue,20%);
$blue-d2: shade($blue,40%);
$blue-d3: shade($blue,60%);
$blue-d4: shade($blue,80%);
$pink: rgb(183, 37, 103);
$pink-l1: tint($pink,20%);
$pink-l2: tint($pink,40%);
$pink-l3: tint($pink,60%);
$pink-l4: tint($pink,80%);
$pink-l5: tint($pink,90%);
$pink-d1: shade($pink,20%);
$pink-d2: shade($pink,40%);
$pink-d3: shade($pink,60%);
$pink-d4: shade($pink,80%);
$green: rgb(37, 184, 90);
$green-l1: tint($green,20%);
$green-l2: tint($green,40%);
$green-l3: tint($green,60%);
$green-l4: tint($green,80%);
$green-l5: tint($green,90%);
$green-d1: shade($green,20%);
$green-d2: shade($green,40%);
$green-d3: shade($green,60%);
$green-d4: shade($green,80%);
$yellow: rgb(231, 214, 143);
$yellow-l1: tint($yellow,20%);
$yellow-l2: tint($yellow,40%);
$yellow-l3: tint($yellow,60%);
$yellow-l4: tint($yellow,80%);
$yellow-l5: tint($yellow,90%);
$yellow-d1: shade($yellow,20%);
$yellow-d2: shade($yellow,40%);
$yellow-d3: shade($yellow,60%);
$yellow-d4: shade($yellow,80%);
$shadow: rgba(0,0,0,0.2);
$shadow-l1: rgba(0,0,0,0.1);
$shadow-d1: rgba(0,0,0,0.4);
// colors - inherited
$baseFontColor: #3c3c3c;
$offBlack: #3c3c3c;
$black: rgb(0,0,0);
$white: rgb(255,255,255);
$blue: #5597dd;
$orange: #edbd3c;
$red: #b20610;
$green: #108614;
......
@import 'bourbon/bourbon';
@import 'bourbon/addons/button';
@import 'vendor/normalize';
@import 'keyframes';
......@@ -8,8 +9,10 @@
@import "fonts";
@import "variables";
@import "cms_mixins";
@import "extends";
@import "base";
@import "header";
@import "footer";
@import "dashboard";
@import "courseware";
@import "subsection";
......@@ -26,6 +29,8 @@
@import "modal";
@import "alerts";
@import "login";
@import "account";
@import "index";
@import 'jquery-ui-calendar';
@import 'content-types';
......
<%inherit file="base.html" />
<%! from django.core.urlresolvers import reverse %>
<%block name="bodyclass">assets</%block>
<%block name="title">Courseware Assets</%block>
<%block name="bodyclass">is-signedin course uploads</%block>
<%block name="title">Uploads &amp; Files</%block>
<%namespace name='static' file='static_content.html'/>
......
......@@ -5,23 +5,29 @@
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>
<%block name="title"></%block> |
% if context_course:
<% ctx_loc = context_course.location %>
${context_course.display_name} |
% endif
edX Studio
</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="path_prefix" content="${MITX_ROOT_URL}">
<%static:css group='base-style'/>
<link rel="stylesheet" type="text/css" href="${static.url('js/vendor/markitup/skins/simple/style.css')}" />
<link rel="stylesheet" type="text/css" href="${static.url('js/vendor/markitup/sets/wiki/style.css')}" />
<link rel="stylesheet" type="text/css" href="${static.url('css/vendor/symbolset.ss-standard.css')}" />
<link rel="stylesheet" type="text/css" href="${static.url('css/vendor/symbolset.ss-symbolicons-block.css')}" />
<title><%block name="title"></%block></title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="path_prefix" content="${MITX_ROOT_URL}">
<link rel="stylesheet" type="text/css" href="${static.url('css/vendor/symbolset.ss-standard.css')}" />
<%block name="header_extras"></%block>
</head>
<body class="<%block name='bodyclass'></%block> hide-wip">
<%include file="widgets/header.html" args="active_tab=active_tab"/>
<%include file="widgets/header.html" />
<%include file="courseware_vendor_js.html"/>
<script type="text/javascript" src="${static.url('js/vendor/json2.js')}"></script>
......@@ -47,9 +53,9 @@
</script>
<%block name="content"></%block>
<%include file="widgets/footer.html" />
<%block name="jsextra"></%block>
</body>
</html>
......
<%inherit file="base.html" />
<%block name="title">Course Manager</%block>
<%include file="widgets/header.html"/>
<%block name="content">
......
......@@ -2,8 +2,9 @@
<%namespace name='static' file='static_content.html'/>
<!-- TODO decode course # from context_course into title -->
<%block name="title">Course Info</%block>
<%block name="bodyclass">course-info</%block>
<%block name="title">Updates</%block>
<%block name="bodyclass">is-signedin course course-info updates</%block>
<%block name="jsextra">
<script type="text/javascript" src="${static.url('js/template_loader.js')}"></script>
......
<%inherit file="base.html" />
<%! from django.core.urlresolvers import reverse %>
<%block name="title">Edit Static Page</%block>
<%block name="bodyclass">edit-static-page</%block>
<%block name="title">Editing Static Page</%block>
<%block name="bodyclass">is-signedin course pages edit-static-page</%block>
<%block name="content">
<div class="main-wrapper">
......
<%inherit file="base.html" />
<%! from django.core.urlresolvers import reverse %>
<%block name="title">Tabs</%block>
<%block name="bodyclass">static-pages</%block>
<%block name="title">Static Pages</%block>
<%block name="bodyclass">is-signedin course pages static-pages</%block>
<%block name="jsextra">
<script type='text/javascript'>
......
......@@ -7,8 +7,9 @@
%>
<%! from django.core.urlresolvers import reverse %>
<%block name="bodyclass">subsection</%block>
<%block name="title">CMS Subsection</%block>
<%block name="bodyclass">is-signedin course subsection</%block>
<%namespace name="units" file="widgets/units.html" />
<%namespace name='static' file='static_content.html'/>
......@@ -97,6 +98,7 @@
</div>
</div>
</div>
</div>
</%block>
<%block name="jsextra">
......
......@@ -2,8 +2,8 @@
<%namespace name='static' file='static_content.html'/>
<%! from django.core.urlresolvers import reverse %>
<%block name="title">Export</%block>
<%block name="bodyclass">export</%block>
<%block name="title">Export Course</%block>
<%block name="bodyclass">is-signedin course tools export</%block>
<%block name="content">
<div class="main-wrapper">
......
<%inherit file="base.html" />
<%! from django.core.urlresolvers import reverse %>
<%block name="title">Welcome</%block>
<%block name="bodyclass">not-signedin index howitworks</%block>
<%block name="content">
<div class="wrapper-content-header wrapper">
<section class="content content-header">
<header>
<h1>Welcome to <span class="logo">edX Studio</span></h1>
<p class="tagline">Studio helps manage your courses online, so you can focus on teaching them</p>
</header>
</section>
</div>
<div class="wrapper-content-features wrapper">
<section class="content content-features">
<header>
<h2 class="sr">Studio's Many Features</h2>
</header>
<ol class="list-features">
<li class="feature">
<figure class="img zoom">
<a rel="modal" href="#hiw-feature1">
<img src="/static/img/thumb-hiw-feature1.png" alt="Studio Helps You Keep Your Courses Organized" />
<figcaption class="sr">Studio Helps You Keep Your Courses Organized</figcaption>
<span class="action-zoom">
<i class="ss-icon ss-symbolicons-block">&#xE002;</i>
</span>
</a>
</figure>
<div class="copy">
<h3>Keeping Your Course Organized</h3>
<p>The backbone of your course is how it is organized. Studio offers an <strong>Outline</strong> editor, providing a simple hierarchy and easy drag and drop to help you and your students stay organized.</p>
<ul class="list-proofpoints">
<li class="proofpoint">
<h4 class="title">Simple Organization For Content</h4>
<p>Studio uses <strong>Sections</strong> and <strong>Learning Sequences</strong> to organize your content into a simple hierarchy.</p>
</li>
<li class="proofpoint">
<h4 class="title">Change Your Mind Anytime</h4>
<p>Draft your outline and build content anywhere. Simple drag and drop tools let your reorganize quickly.</p>
</li>
<li class="proofpoint">
<h4 class="title">Go A Week Or A Semester At A Time</h4>
<p>Build and release <strong>Sections</strong> to your students incrementally. You don't have to have it all done at once.</p>
</li>
</ul>
</div>
</li>
<li class="feature">
<figure class="img zoom">
<a rel="modal" href="#hiw-feature2">
<img src="/static/img/thumb-hiw-feature2.png" alt="Studio Keeps Your Learning Sequences and Lectures, Together" />
<figcaption class="sr">Studio Keeps Your Learning Sequences and Lectures, Together</figcaption>
<span class="action-zoom">
<i class="ss-icon ss-symbolicons-block">&#xE002;</i>
</span>
</a>
</figure>
<div class="copy">
<h3>Learning Sequences: Lectures and Exercises, Together </h3>
<p>The heart of the student experience is being immersed in <strong>Learning Sequences</strong> &mdash; short video lectures interleaved with exercises. Studio allows you to insert videos and author a wide variety of exercise types with just a few clicks. </p>
<ul class="list-proofpoints">
<li class="proofpoint">
<h4 class="title">Create Learning Pathways</h4>
<p>Help your students understand a small interactive piece at a time. <strong>Learning Sequences</strong> are built from <strong>Learning Units</strong>.</p>
</li>
<li class="proofpoint">
<h4 class="title">Work Visually, Organize Quickly</h4>
<p>Work visually and see exactly what your students will see. Reorganize your <strong>Learning Units</strong> with drag and drop.</p>
</li>
<li class="proofpoint">
<h4 class="title">A Broad Library of Problem Types</h4>
<p>It's more than just multiple choice. Studio has nearly a dozen types of problems to challenge your learners.</p>
</li>
</ul>
</div>
</li>
<li class="feature">
<figure class="img zoom">
<a rel="modal" href="#hiw-feature3">
<img src="/static/img/thumb-hiw-feature3.png" alt="Studio Gives You Simple, Fast, and Incremental Publishing. With Friends." />
<figcaption class="sr">Studio Gives You Simple, Fast, and Incremental Publishing. With Friends.</figcaption>
<span class="action-zoom">
<i class="ss-icon ss-symbolicons-block">&#xE002;</i>
</span>
</a>
</figure>
<div class="copy">
<h3>Simple, Fast, and Incremental Publishing. With Friends.</h3>
<p>Studio works like web applications you already know, yet understands how you build curriculum. Instant publishing to the web when you want it, incremental release when it makes sense. And with co-authors, you can have a whole team building a course, together.</p>
<ul class="list-proofpoints">
<li class="proofpoint">
<h4 class="title">Instant Changes</h4>
<p>Caught a bug? No problem. When you want, your changes to live when you hit Save.</p>
</li>
<li class="proofpoint">
<h4 class="title">Release-On Date Publishing</h4>
<p>When you've finished a <strong>Section</strong>, pick when you want it to go live and Studio takes care of the rest. Build your course incrementally.</p>
</li>
<li class="proofpoint">
<h4 class="title">Work in Teams</h4>
<p>Co-authors have full access to all the same authoring tools. Make your course better through a team effort.</p>
</li>
</ul>
</div>
</li>
</ol>
</section>
</div>
<div class="wrapper-content-cta wrapper">
<section class="content content-cta">
<header>
<h2 class="sr">Sign Up for Studio Today!</h2>
</header>
<ul class="list-actions">
<li>
<a href="${reverse('signup')}" class="action action-primary">Sign Up &amp; Start Making an edX Course</a>
</li>
<li>
<a href="${reverse('login')}" class="action action-secondary">Already have a Studio Account? Sign In</a>
</li>
</ul>
</section>
</div>
<div class="content-modal" id="hiw-feature1">
<h3 class="title">Outlining Your Course</h3>
<figure>
<img src="/static/img/hiw-feature1.png" alt="" />
<figcaption class="description">Simple two-level outline to organize your couse. Drag and drop, and see your course at a glance.</figcaption>
</figure>
<a href="#" rel="view" class="action action-modal-close">
<i class="ss-icon ss-symbolicons-block">&#x2421;</i>
<span class="label">close modal</span>
</a>
</div>
<div class="content-modal" id="hiw-feature2">
<h3 class="title">Editing a Learning Sequence</h3>
<figure>
<img src="/static/img/hiw-feature2.png" alt="" />
<figcaption class="description">Quickly create videos, text snippets, inline discussions, and a variety of problem types.</figcaption>
</figure>
<a href="#" rel="view" class="action action-modal-close">
<i class="ss-icon ss-symbolicons-block">&#x2421;</i>
<span class="label">close modal</span>
</a>
</div>
<div class="content-modal" id="hiw-feature3">
<h3 class="title">Publishing on Date</h3>
<figure>
<img src="/static/img/hiw-feature3.png" alt="" />
<figcaption class="description">Simply set the date on a Section or Learning Sequence, and Studio will publish it to your students for you.</figcaption>
</figure>
<a href="#" rel="view" class="action action-modal-close">
<i class="ss-icon ss-symbolicons-block">&#x2421;</i>
<span class="label">close modal</span>
</a>
</div>
</%block>
<%block name="jsextra">
<script type="text/javascript">
(function() {
// lean modal window
$('a[rel*=modal]').leanModal({overlay : 0.50, closeButton: '.action-modal-close' });
$('a.action-modal-close').click(function(e){
(e).preventDefault();
});
})(this)
</script>
</%block>
\ No newline at end of file
......@@ -2,8 +2,8 @@
<%namespace name='static' file='static_content.html'/>
<%! from django.core.urlresolvers import reverse %>
<%block name="title">Import</%block>
<%block name="bodyclass">import</%block>
<%block name="title">Import Course</%block>
<%block name="bodyclass">is-signedin course tools import</%block>
<%block name="content">
<div class="main-wrapper">
......
<%inherit file="base.html" />
<%block name="bodyclass">index</%block>
<%block name="title">Courses</%block>
<%block name="bodyclass">is-signedin index dashboard</%block>
<%block name="header_extras">
<script type="text/template" id="new-course-template">
......
<%inherit file="base.html" />
<%! from django.core.urlresolvers import reverse %>
<%block name="title">Log in</%block>
<%block name="bodyclass">no-header</%block>
<%block name="title">Sign In</%block>
<%block name="bodyclass">not-signedin signin</%block>
<%block name="content">
<div class="edx-studio-logo-large"></div>
<article class="log-in-box">
<div class="wrapper-content wrapper">
<section class="content">
<header>
<h1>Log in to edX studio</h1>
<h1 class="title title-1">Sign into edX Studio</h1>
<a href="${reverse('signup')}" class="action action-signin">Don't have a Studio Account? Sign up!</a>
</header>
<form class="log-in-form" id="login_form" action="login_post" method="post">
<div class="row">
<label>Email</label>
<input name="email" type="email" class="email-field" tabindex="1">
</div>
<div class="row">
<label>Password <a href="${forgot_password_link}" class="forgot-button">Forgot password?</a></label>
<input name="password" type="password" class="password-field" tabindex="2">
</div>
<div class="row form-actions">
<input name="submit" type="submit" value="Log In" class="log-in-button" tabindex="3">
<span class="or">or</span>
<a href="${reverse('signup')}" class="sign-up-button" tabindex="4">Sign up</a>
<article class="content-primary" role="main">
<form id="login_form" method="post" action="login_post">
<fieldset>
<legend class="sr">Required Information to Sign into edX Studio</legend>
<ol class="list-input">
<li class="field text required" id="field-email">
<label for="email">Email Address</label>
<input id="email" type="email" name="email" placeholder="e.g. jane.doe@gmail.com" />
</li>
<li class="field text required" id="field-password">
<a href="${forgot_password_link}" class="action action-forgotpassword" tabindex="-1">Forgot password?</a>
<label for="password">Password</label>
<input id="password" type="password" name="password" />
</li>
</ol>
</fieldset>
<div class="form-actions">
<button type="submit" id="submit" name="submit" class="action action-primary">Sign into edX Studio</button>
</div>
<!-- no honor code for CMS, but need it because we're using the lms student object -->
<input name="honor_code" type="checkbox" value="true" checked="true" hidden="true">
</form>
</article>
<aside class="content-supplementary" role="complimentary">
<h2 class="sr">Studio Support</h2>
<div class="bit">
<h3 class="title-3">Need Help?</h3>
<p>Having trouble with your account? Use <a href="" rel="external">our support center</a> to look over self help steps, find solutions others have found to the same problem, or let us know of your issue.</p>
</div>
</aside>
</section>
</div>
</%block>
<%block name="jsextra">
<script type="text/javascript">
(function() {
function getCookie(name) {
......@@ -53,10 +79,10 @@
if(json.success) {
location.href = "${reverse('index')}";
} else if($('#login_error').length == 0) {
$('#login_form').prepend('<div id="login_error">' + json.value + '</div>');
$('#login_error').slideDown(150);
$('#login_form').prepend('<div id="login_error" class="message message-status error">' + json.value + '</span></div>');
$('#login_error').addClass('is-shown');
} else {
$('#login_error').stop().slideDown(150);
$('#login_error').stop().addClass('is-shown');
$('#login_error').html(json.value);
}
}
......@@ -64,5 +90,4 @@
});
})(this)
</script>
</%block>
\ No newline at end of file
<%inherit file="base.html" />
<%block name="title">Course Staff Manager</%block>
<%block name="bodyclass">users</%block>
<%block name="bodyclass">is-signedin course users settings team</%block>
<%block name="content">
<div class="main-wrapper">
......
......@@ -6,7 +6,8 @@
from datetime import datetime
%>
<%! from django.core.urlresolvers import reverse %>
<%block name="title">CMS Courseware Overview</%block>
<%block name="title">Course Outline</%block>
<%block name="bodyclass">is-signedin course outline</%block>
<%namespace name='static' file='static_content.html'/>
<%namespace name="units" file="widgets/units.html" />
......
<%inherit file="base.html" />
<%block name="title">Grading</%block>
<%block name="bodyclass">is-signedin course grading settings</%block>
<%namespace name='static' file='static_content.html'/>
<%!
from contentstore import utils
%>
<%block name="jsextra">
<link rel="stylesheet" type="text/css" href="${static.url('js/vendor/timepicker/jquery.timepicker.css')}" />
<script src="${static.url('js/vendor/timepicker/jquery.timepicker.js')}"></script>
<script type="text/javascript" src="${static.url('js/template_loader.js')}"></script>
<script type="text/javascript" src="${static.url('js/views/server_error.js')}"></script>
<script type="text/javascript" src="${static.url('js/models/course_relative.js')}"></script>
<script type="text/javascript" src="${static.url('js/views/validating_view.js')}"></script>
<script type="text/javascript" src="${static.url('js/models/settings/course_grading_policy.js')}"></script>
<script type="text/javascript" src="${static.url('js/views/settings/settings_grading_view.js')}"></script>
<script type="text/javascript">
$(document).ready(function(){
$("form :input").focus(function() {
$("label[for='" + this.id + "']").addClass("is-focused");
}).blur(function() {
$("label").removeClass("is-focused");
});
var editor = new CMS.Views.Settings.Grading({
el: $('.settings-grading'),
model : new CMS.Models.Settings.CourseGradingPolicy(${course_details|n},{parse:true})
});
editor.render();
});
</script>
</%block>
<%block name="content">
<div class="wrapper-content wrapper">
<section class="content">
<header class="page">
<span class="title-sub">Settings</span>
<h1 class="title-1">Grading</h1>
</header>
<!-- <div class="introduction">
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem.</p>
</div> -->
<article class="content-primary" role="main">
<form id="settings_details" class="settings-grading" method="post" action="">
<section class="group-settings grade-range">
<header>
<h2 class="title-2">Overall Grade Range</h2>
<span class="tip">Your overall grading scale for student final grades</span>
</header>
<ol class="list-input">
<li class="field" id="field-course-grading-range">
<div class="grade-controls course-grading-range well">
<a href="#" class="new-grade-button"><span class="plus-icon"></span></a>
<div class="grade-slider">
<div class="grade-bar">
<ol class="increments">
<li class="increment-0">0</li>
<li class="increment-10">10</li>
<li class="increment-20">20</li>
<li class="increment-30">30</li>
<li class="increment-40">40</li>
<li class="increment-50">50</li>
<li class="increment-60">60</li>
<li class="increment-70">70</li>
<li class="increment-80">80</li>
<li class="increment-90">90</li>
<li class="increment-100">100</li>
</ol>
<ol class="grades">
</ol>
</div>
</div>
</div>
</li>
</ol>
</section>
<hr class="divide" />
<section class="group-settings grade-rules">
<header>
<h2 class="title-2">Grading Rules &amp; Policies</h2>
<span class="tip">Deadlines, requirements, and logistics around grading student work</span>
</header>
<ol class="list-input">
<li class="field text" id="field-course-grading-graceperiod">
<label for="course-grading-graceperiod">Grace Period on Deadline:</label>
<input type="text" class="short time" id="course-grading-graceperiod" value="0:00" placeholder="e.g. 10 minutes">
<span class="tip tip-inline">Leeway on due dates</span>
</li>
</ol>
</section>
<hr class="divide" />
<section class="group-settings assignment-types">
<header>
<h2 class="title-2">Assignment Types</h2>
<span class="tip">Categories and labels for any exercises that are gradable</span>
</header>
<ol class="list-input course-grading-assignment-list enum">
</ol>
<div class="actions">
<a href="#" class="new-button new-course-grading-item add-grading-data">
<span class="plus-icon white"></span>New Assignment Type
</a>
</div>
</section>
</form>
</article>
<aside class="content-supplementary" role="complimentary">
<div class="bit">
<h3 class="title-3">How will these settings be used</h3>
<p>Your grading settings will be used to calculate students grades and performance.</p>
<p>Overall grade range will be used in students' final grades, which are calculated by the weighting you determine for each custom assignment type.</p>
</div>
<div class="bit">
% if context_course:
<% ctx_loc = context_course.location %>
<%! from django.core.urlresolvers import reverse %>
<h3 class="title-3">Other Course Settings</h3>
<nav class="nav-related">
<ul>
<li class="nav-item"><a href="${reverse('contentstore.views.get_course_settings', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}">Details &amp; Schedule</a></li>
</ul>
</nav>
% endif
</div>
</aside>
</section>
</div>
</%block>
<%inherit file="base.html" />
<%! from django.core.urlresolvers import reverse %>
<%block name="title">Sign up</%block>
<%block name="bodyclass">no-header</%block>
<%block name="title">Sign Up</%block>
<%block name="bodyclass">not-signedin signup</%block>
<%block name="content">
<div class="edx-studio-logo-large"></div>
<article class="sign-up-box">
<div class="wrapper-content wrapper">
<section class="content">
<header>
<h1>Register for edX studio</h1>
<h1 class="title title-1">Sign Up for edX Studio</h1>
<a href="${reverse('login')}" class="action action-signin">Already have a Studio Account? Sign in</a>
</header>
<form id="register_form" method="post">
<div id="register_error" name="register_error"></div>
<div class="row">
<label>Email</label>
<input name="email" type="email">
</div>
<div class="row">
<label>Password</label>
<input name="password" type="password">
</div>
<div class="row">
<label>Public Username</label>
<input name="username" type="text">
</div>
<div class="row">
<label>Full Name</label>
<input name="name" type="text">
</div>
<div class="row">
<div class="split">
<label>Your Location</label>
<input name="location" type="text">
<p class="introduction">Ready to start creating online courses? Sign up below and start creating your first edX course today.</p>
<article class="content-primary" role="main">
<form id="register_form" method="post" action="register_post">
<div id="register_error" name="register_error" class="message message-status message-status error">
</div>
<div class="split">
<label>Preferred Language</label>
<input name="language" type="text">
<fieldset>
<legend class="sr">Required Information to Sign Up for edX Studio</legend>
<ol class="list-input">
<li class="field text required" id="field-email">
<label for="email">Email Address</label>
<input id="email" type="email" name="email" placeholder="e.g. jane.doe@gmail.com" />
</li>
<li class="field text required" id="field-password">
<label for="password">Password</label>
<input id="password" type="password" name="password" />
</li>
<li class="field text required" id="field-username">
<label for="username">Public Username</label>
<input id="username" type="text" name="username" placeholder="e.g. janedoe" />
<span class="tip tip-stacked">This will be used in public discussions with your courses and in our edX101 support forums</span>
</li>
<li class="field text required" id="field-name">
<label for="name">Full Name</label>
<input id="name" type="text" name="name" placeholder="e.g. Jane Doe" />
</li>
<li class="field-group">
<div class="field text" id="field-location">
<label for="location">Your Location</label>
<input class="short" id="location" type="text" name="location" />
</div>
<div class="field text" id="field-language">
<label for="language">Preferred Language</label>
<input class="short" id="language" type="text" name="language" />
</div>
<div class="row">
<label class="terms-of-service">
<input name="terms_of_service" type="checkbox" value="true">
I agree to the
<a href="#">Terms of Service</a>
</label>
</li>
<li class="field checkbox required" id="field-tos">
<input id="tos" name="terms_of_service" type="checkbox" value="true" />
<label for="tos">I agree to the Terms of Service</label>
</li>
</ol>
</fieldset>
<div class="form-actions">
<button type="submit" id="submit" name="submit" class="action action-primary">Create My Account & Start Authoring Courses</button>
</div>
<!-- no honor code for CMS, but need it because we're using the lms student object -->
<input name="honor_code" type="checkbox" value="true" checked="true" hidden="true">
</form>
</article>
<aside class="content-supplementary" role="complimentary">
<h2 class="sr">Common Studio Questions</h2>
<div class="row form-actions submit">
<input name="submit" type="submit" value="Create My Account" class="create-account-button">
<p class="enrolled">Already enrolled? <a href="/">Log In.</a></p>
<div class="bit">
<h3 class="title-3">Who is Studio for?</h3>
<p>Studio is for anyone that wants to create online courses that leverage the global edX platform. Our users are often faculty members, teaching assistants and course staff, and members of instructional technology groups.</p>
</div>
<div class="bit">
<h3 class="title-3">How technically savvy do I need to be to create courses in Studio?</h3>
<p>Studio is designed to be easy to use by almost anyone familiar with common web-based authoring environments (Wordpress, Moodle, etc.). No programming knowledge is required, but for some of the more advanced features, a technical background would be helpful. As always, we are here to help, so don't hesitate to dive right in.</p>
</div>
</form>
</article>
<script type="text/javascript">
<div class="bit">
<h3 class="title-3">I've never authored a course online before. Is there help?</h3>
<p>Absolutely. We have created an online course, edX101, that describes some best practices: from filming video, creating exercises, to the basics of running an online course. Additionally, we're always here to help, just drop us a note.</p>
</div>
</aside>
</section>
</div>
</%block>
<%block name="jsextra">
<script type="text/javascript">
(function() {
$("form :input").focus(function() {
$("label[for='" + this.id + "']").addClass("is-focused");
}).blur(function() {
$("label").removeClass("is-focused");
});
function getCookie(name) {
return $.cookie(name);
}
// form validation
function postJSON(url, data, callback) {
$.ajax({type:'POST',
url: url,
......@@ -84,11 +131,11 @@
if(json.success) {
location.href = "${reverse('index')}";
} else {
$('#register_error').html(json.value).stop().slideDown(150);
$('#register_error').html(json.value).stop().addClass('is-shown');
}
}
);
});
})(this)
</script>
</script>
</%block>
\ No newline at end of file
<%inherit file="base.html" />
<%! from django.core.urlresolvers import reverse %>
<%namespace name="units" file="widgets/units.html" />
<%block name="bodyclass">unit</%block>
<%block name="title">CMS Unit</%block>
<%block name="title">Individual Unit</%block>
<%block name="bodyclass">is-signedin course unit</%block>
<%block name="jsextra">
<script type='text/javascript'>
$(document).ready(function() {
......
<%! from django.core.urlresolvers import reverse %>
<div class="wrapper-footer wrapper">
<footer class="primary" role="contentinfo">
<div class="colophon">
<p>&copy; 2013 <a href="http://www.edx.org" rel="external">edX</a>. All rights reserved.</p>
</div>
<nav class="nav-peripheral">
<ol>
<!-- <li class="nav-item nav-peripheral-tos">
<a href="#">Terms of Service</a>
</li>
<li class="nav-item nav-peripheral-pp">
<a href="#">Privacy Policy</a>
</li> -->
<li class="nav-item nav-peripheral-help">
<a href="http://help.edge.edx.org/" rel="external">edX Studio Help</a>
</li>
<li class="nav-item nav-peripheral-contact">
<a href="#">Contact edX</a>
</li>
% if user.is_authenticated():
<!-- add in zendesk/tender feedback form UI -->
% endif
</ol>
</nav>
</footer>
</div>
\ No newline at end of file
<%! from django.core.urlresolvers import reverse %>
<% active_tab_class = 'active-tab-' + active_tab if active_tab else '' %>
<header class="primary-header ${active_tab_class}">
<div class="class">
<div class="inner-wrapper">
<div class="left">
<div class="wrapper-header wrapper">
<header class="primary" role="banner">
<div class="wrapper wrapper-left ">
<h1 class="branding"><a href="/">edX Studio</a></h1>
% if context_course:
<% ctx_loc = context_course.location %>
<a href="/" class="home"><span class="small-home-icon"></span></a>
<a href="${reverse('course_index', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}" class="class-name">${context_course.display_name}</a>
% endif
<div class="info-course">
<h2 class="sr">Current Course:</h2>
<a href="${reverse('course_index', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}">
<span class="course-org">${ctx_loc.org}</span><span class="course-number">${ctx_loc.course}</span>
<span class="course-title" title="${context_course.display_name}">${context_course.display_name}</span>
</a>
</div>
<div class="right">
<span class="username">${ user.username }</span>
% if user.is_authenticated():
<a href="${reverse('logout')}" class="log-out"><span class="log-out-icon"></span></a>
% else:
<a href="${reverse('login')}">Log in</a>
% endif
<nav class="nav-course primary nav-dropdown" role="navigation">
<h2 class="sr">PH207x's Navigation:</h2>
<ol>
<li class="nav-item nav-course-courseware">
<h3 class="title"><span class="label-prefix">Course </span>Content <i class="ss-icon ss-symbolicons-block icon-expand">&#x25BE;</i></h3>
<div class="wrapper wrapper-nav-sub">
<div class="nav-sub">
<ul>
<li class="nav-item nav-course-courseware-outline"><a href="${reverse('course_index', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}">Outline</a></li>
<li class="nav-item nav-course-courseware-updates"><a href="${reverse('course_info', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}">Updates</a></li>
<li class="nav-item nav-course-courseware-pages"><a href="${reverse('edit_tabs', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, coursename=ctx_loc.name))}">Static Pages</a></li>
<li class="nav-item nav-course-courseware-uploads"><a href="${reverse('asset_index', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}">Files &amp; Uploads</a></li>
</ul>
</div>
</div>
</li>
<li class="nav-item nav-course-settings">
<h3 class="title"><span class="label-prefix">Course </span>Settings <i class="ss-icon ss-symbolicons-block icon-expand">&#x25BE;</i></h3>
<div class="wrapper wrapper-nav-sub">
<div class="nav-sub">
<ul>
<li class="nav-item nav-course-settings-schedule"><a href="${reverse('contentstore.views.get_course_settings', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}">Schedule &amp; Details</a></li>
<li class="nav-item nav-course-settings-grading"><a href="${reverse('contentstore.views.course_config_graders_page', kwargs={'org' : ctx_loc.org, 'course' : ctx_loc.course, 'name': ctx_loc.name})}">Grading</a></li>
<li class="nav-item nav-course-settings-team"><a href="${reverse('manage_users', kwargs=dict(location=ctx_loc))}">Course Team</a></li>
<!-- <li class="nav-item nav-course-settings-advanced"><a href="${reverse('course_settings', kwargs={'org' : ctx_loc.org, 'course' : ctx_loc.course, 'name': ctx_loc.name})}">Advanced Settings</a></li> -->
</ul>
</div>
</div>
<nav class="class-nav-bar">
% if context_course:
<% ctx_loc = context_course.location %>
<ul class="class-nav inner-wrapper">
<li><a href="${reverse('course_index', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}" id='courseware-tab'>Courseware</a></li>
<li><a href="${reverse('course_info', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}" id='courseinfo-tab'>Course Info</a></li>
<li><a href="${reverse('edit_tabs', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, coursename=ctx_loc.name))}" id='pages-tab'>Pages</a></li>
<li><a href="${reverse('manage_users', kwargs=dict(location=ctx_loc))}" id='users-tab'>Users</a></li>
<li><a href="${reverse('asset_index', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}" id='assets-tab'>Assets</a></li>
<li><a href="${reverse('course_settings', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}" id='settings-tab'>Settings</a></li>
<li><a href="${reverse('import_course', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}" id='import-tab'>Import</a></li>
<li><a href="${reverse('export_course', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}" id='export-tab'>Export</a></li>
</li>
<li class="nav-item nav-course-tools">
<h3 class="title">Tools <i class="ss-icon ss-symbolicons-block icon-expand">&#x25BE;</i></h3>
<div class="wrapper wrapper-nav-sub">
<div class="nav-sub">
<ul>
<li class="nav-item nav-course-tools-import"><a href="${reverse('import_course', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}">Import</a></li>
<li class="nav-item nav-course-tools-export"><a href="${reverse('export_course', kwargs=dict(org=ctx_loc.org, course=ctx_loc.course, name=ctx_loc.name))}">Export</a></li>
</ul>
</div>
</div>
</li>
</ol>
</nav>
% endif
</div>
<div class="wrapper wrapper-right">
% if user.is_authenticated():
<nav class="nav-account nav-is-signedin nav-dropdown">
<h2 class="sr">Currently logged in as:</h2>
<ol>
<li class="nav-item nav-account-username">
<a href="#" class="title">
<span class="account-username">
<i class="ss-icon ss-symbolicons-standard icon-user">&#x1F464;</i>
${ user.username }
</span>
<i class="ss-icon ss-symbolicons-block icon-expand">&#x25BE;</i>
</a>
<div class="wrapper wrapper-nav-sub">
<div class="nav-sub">
<ul>
<li class="nav-item nav-account-dashboard"><a href="#">My Courses</a></li>
<li class="nav-item nav-account-help"><a href="http://help.edge.edx.org/" rel="external">Studio Help</a></li>
<li class="nav-item nav-account-signout"><a class="action action-signout" href="${reverse('logout')}">Sign Out</a></li>
</ul>
</div>
</div>
</li>
</ol>
</nav>
</header>
% else:
<nav class="nav-not-signedin">
<h2 class="sr">You're not currently signed in</h2>
<ol>
<li class="nav-item nav-not-signedin-hiw">
<a href="#">How Studio Works</a>
</li>
<li class="nav-item nav-not-signedin-help">
<a href="http://help.edge.edx.org/" rel="external">Studio Help</a>
</li>
<li class="nav-item nav-not-signedin-signup">
<a class="action action-signup" href="${reverse('signup')}">Sign Up</a>
</li>
<li class="nav-item nav-not-signedin-signin">
<a class="action action-signin" href="${reverse('login')}">Sign In</a>
</li>
</ol>
</nav>
% endif
</div>
</header>
</div>
\ No newline at end of file
......@@ -42,9 +42,10 @@ urlpatterns = ('',
'contentstore.views.remove_user', name='remove_user'),
url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/info/(?P<name>[^/]+)$', 'contentstore.views.course_info', name='course_info'),
url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/course_info/updates/(?P<provided_id>.*)$', 'contentstore.views.course_info_updates', name='course_info'),
url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/settings/(?P<name>[^/]+)$', 'contentstore.views.get_course_settings', name='course_settings'),
url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/settings/(?P<name>[^/]+)/section/(?P<section>[^/]+).*$', 'contentstore.views.course_settings_updates', name='course_settings'),
url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/grades/(?P<name>[^/]+)/(?P<grader_index>.*)$', 'contentstore.views.course_grader_updates', name='course_settings'),
url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/settings-details/(?P<name>[^/]+)$', 'contentstore.views.get_course_settings', name='course_settings'),
url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/settings-grading/(?P<name>[^/]+)$', 'contentstore.views.course_config_graders_page', name='course_settings'),
url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/settings-details/(?P<name>[^/]+)/section/(?P<section>[^/]+).*$', 'contentstore.views.course_settings_updates', name='course_settings'),
url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/settings-grading/(?P<name>[^/]+)/(?P<grader_index>.*)$', 'contentstore.views.course_grader_updates', name='course_settings'),
url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/(?P<category>[^/]+)/(?P<name>[^/]+)/gradeas.*$', 'contentstore.views.assignment_type_update', name='assignment_type_update'),
......@@ -76,6 +77,7 @@ urlpatterns = ('',
# User creation and updating views
urlpatterns += (
url(r'^howitworks$', 'contentstore.views.howitworks', name='howitworks'),
url(r'^signup$', 'contentstore.views.signup', name='signup'),
url(r'^create_account$', 'student.views.create_account'),
......
// font-sizing
@function em($pxval, $base: 16) {
@return #{$pxval / $base}em;
}
// Line-height
@mixin font-size($sizeValue: 1.6){
font-size: $sizeValue + px;
font-size: ($sizeValue/10) + rem;
}
// line-height
@function lh($amount: 1) {
@return $body-line-height * $amount;
}
@mixin hide-text(){
text-indent: -9999px;
// image-replacement hidden text
@mixin text-hide() {
text-indent: -100%;
white-space: nowrap;
overflow: hidden;
}
// hidden elems - screenreaders
@mixin text-sr() {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
display: block;
padding: 0;
position: absolute;
width: 1px;
}
@mixin vertically-and-horizontally-centered ( $height, $width ) {
// vertical and horizontal centering
@mixin vertically-and-horizontally-centered ($height, $width) {
left: 50%;
margin-left: -$width / 2;
//margin-top: -$height / 2;
......@@ -22,3 +42,26 @@
position: absolute;
top: 150px;
}
// sizing
@mixin size($width: $baseline, $height: $baseline) {
height: $height;
width: $width;
}
@mixin square($size: $baseline) {
@include size($size);
}
// placeholder styling
@mixin placeholder($color) {
:-moz-placeholder {
color: $color;
}
::-webkit-input-placeholder {
color: $color;
}
:-ms-input-placeholder {
color: $color;
}
}
\ No newline at end of file
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