Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
200493a5
Commit
200493a5
authored
Jan 06, 2013
by
ichuang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
instructor dashboard upgrade - add enrollment management
parent
e97469ae
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
568 additions
and
23 deletions
+568
-23
common/djangoapps/student/migrations/0021_auto__add_courseenrollmentallowed__add_unique_courseenrollmentallowed_.py
+156
-0
common/djangoapps/student/migrations/0021_remove_askbot.py.old
+157
-0
common/djangoapps/student/models.py
+18
-0
lms/djangoapps/instructor/views.py
+185
-20
lms/envs/dev.py
+4
-0
lms/templates/courseware/instructor_dashboard.html
+48
-3
No files found.
common/djangoapps/student/migrations/0021_auto__add_courseenrollmentallowed__add_unique_courseenrollmentallowed_.py
0 → 100644
View file @
200493a5
# -*- coding: utf-8 -*-
import
datetime
from
south.db
import
db
from
south.v2
import
SchemaMigration
from
django.db
import
models
class
Migration
(
SchemaMigration
):
def
forwards
(
self
,
orm
):
# Adding model 'CourseEnrollmentAllowed'
db
.
create_table
(
'student_courseenrollmentallowed'
,
(
(
'id'
,
self
.
gf
(
'django.db.models.fields.AutoField'
)(
primary_key
=
True
)),
(
'email'
,
self
.
gf
(
'django.db.models.fields.CharField'
)(
max_length
=
255
,
db_index
=
True
)),
(
'course_id'
,
self
.
gf
(
'django.db.models.fields.CharField'
)(
max_length
=
255
,
db_index
=
True
)),
(
'created'
,
self
.
gf
(
'django.db.models.fields.DateTimeField'
)(
auto_now_add
=
True
,
null
=
True
,
db_index
=
True
,
blank
=
True
)),
))
db
.
send_create_signal
(
'student'
,
[
'CourseEnrollmentAllowed'
])
# Adding unique constraint on 'CourseEnrollmentAllowed', fields ['email', 'course_id']
db
.
create_unique
(
'student_courseenrollmentallowed'
,
[
'email'
,
'course_id'
])
def
backwards
(
self
,
orm
):
# Removing unique constraint on 'CourseEnrollmentAllowed', fields ['email', 'course_id']
db
.
delete_unique
(
'student_courseenrollmentallowed'
,
[
'email'
,
'course_id'
])
# Deleting model 'CourseEnrollmentAllowed'
db
.
delete_table
(
'student_courseenrollmentallowed'
)
models
=
{
'auth.group'
:
{
'Meta'
:
{
'object_name'
:
'Group'
},
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'unique'
:
'True'
,
'max_length'
:
'80'
}),
'permissions'
:
(
'django.db.models.fields.related.ManyToManyField'
,
[],
{
'to'
:
"orm['auth.Permission']"
,
'symmetrical'
:
'False'
,
'blank'
:
'True'
})
},
'auth.permission'
:
{
'Meta'
:
{
'ordering'
:
"('content_type__app_label', 'content_type__model', 'codename')"
,
'unique_together'
:
"(('content_type', 'codename'),)"
,
'object_name'
:
'Permission'
},
'codename'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
}),
'content_type'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'to'
:
"orm['contenttypes.ContentType']"
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'50'
})
},
'auth.user'
:
{
'Meta'
:
{
'object_name'
:
'User'
},
'date_joined'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'email'
:
(
'django.db.models.fields.EmailField'
,
[],
{
'max_length'
:
'75'
,
'blank'
:
'True'
}),
'first_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'30'
,
'blank'
:
'True'
}),
'groups'
:
(
'django.db.models.fields.related.ManyToManyField'
,
[],
{
'to'
:
"orm['auth.Group']"
,
'symmetrical'
:
'False'
,
'blank'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'is_active'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'True'
}),
'is_staff'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'is_superuser'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'last_login'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'last_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'30'
,
'blank'
:
'True'
}),
'password'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'128'
}),
'user_permissions'
:
(
'django.db.models.fields.related.ManyToManyField'
,
[],
{
'to'
:
"orm['auth.Permission']"
,
'symmetrical'
:
'False'
,
'blank'
:
'True'
}),
'username'
:
(
'django.db.models.fields.CharField'
,
[],
{
'unique'
:
'True'
,
'max_length'
:
'30'
})
},
'contenttypes.contenttype'
:
{
'Meta'
:
{
'ordering'
:
"('name',)"
,
'unique_together'
:
"(('app_label', 'model'),)"
,
'object_name'
:
'ContentType'
,
'db_table'
:
"'django_content_type'"
},
'app_label'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'model'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
}),
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
})
},
'student.courseenrollment'
:
{
'Meta'
:
{
'unique_together'
:
"(('user', 'course_id'),)"
,
'object_name'
:
'CourseEnrollment'
},
'course_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'db_index'
:
'True'
}),
'created'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now_add'
:
'True'
,
'null'
:
'True'
,
'db_index'
:
'True'
,
'blank'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'user'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'to'
:
"orm['auth.User']"
})
},
'student.courseenrollmentallowed'
:
{
'Meta'
:
{
'unique_together'
:
"(('email', 'course_id'),)"
,
'object_name'
:
'CourseEnrollmentAllowed'
},
'course_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'db_index'
:
'True'
}),
'created'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now_add'
:
'True'
,
'null'
:
'True'
,
'db_index'
:
'True'
,
'blank'
:
'True'
}),
'email'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'db_index'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
})
},
'student.pendingemailchange'
:
{
'Meta'
:
{
'object_name'
:
'PendingEmailChange'
},
'activation_key'
:
(
'django.db.models.fields.CharField'
,
[],
{
'unique'
:
'True'
,
'max_length'
:
'32'
,
'db_index'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'new_email'
:
(
'django.db.models.fields.CharField'
,
[],
{
'db_index'
:
'True'
,
'max_length'
:
'255'
,
'blank'
:
'True'
}),
'user'
:
(
'django.db.models.fields.related.OneToOneField'
,
[],
{
'to'
:
"orm['auth.User']"
,
'unique'
:
'True'
})
},
'student.pendingnamechange'
:
{
'Meta'
:
{
'object_name'
:
'PendingNameChange'
},
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'new_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'blank'
:
'True'
}),
'rationale'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'1024'
,
'blank'
:
'True'
}),
'user'
:
(
'django.db.models.fields.related.OneToOneField'
,
[],
{
'to'
:
"orm['auth.User']"
,
'unique'
:
'True'
})
},
'student.registration'
:
{
'Meta'
:
{
'object_name'
:
'Registration'
,
'db_table'
:
"'auth_registration'"
},
'activation_key'
:
(
'django.db.models.fields.CharField'
,
[],
{
'unique'
:
'True'
,
'max_length'
:
'32'
,
'db_index'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'user'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'to'
:
"orm['auth.User']"
,
'unique'
:
'True'
})
},
'student.testcenteruser'
:
{
'Meta'
:
{
'object_name'
:
'TestCenterUser'
},
'address_1'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'40'
}),
'address_2'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'40'
,
'blank'
:
'True'
}),
'address_3'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'40'
,
'blank'
:
'True'
}),
'candidate_id'
:
(
'django.db.models.fields.IntegerField'
,
[],
{
'null'
:
'True'
,
'db_index'
:
'True'
}),
'city'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'32'
,
'db_index'
:
'True'
}),
'client_candidate_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'50'
,
'db_index'
:
'True'
}),
'company_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'50'
,
'blank'
:
'True'
}),
'country'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'3'
,
'db_index'
:
'True'
}),
'created_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now_add'
:
'True'
,
'db_index'
:
'True'
,
'blank'
:
'True'
}),
'extension'
:
(
'django.db.models.fields.CharField'
,
[],
{
'db_index'
:
'True'
,
'max_length'
:
'8'
,
'blank'
:
'True'
}),
'fax'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'35'
,
'blank'
:
'True'
}),
'fax_country_code'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'3'
,
'blank'
:
'True'
}),
'first_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'30'
,
'db_index'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'last_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'50'
,
'db_index'
:
'True'
}),
'middle_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'30'
,
'blank'
:
'True'
}),
'phone'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'35'
}),
'phone_country_code'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'3'
,
'db_index'
:
'True'
}),
'postal_code'
:
(
'django.db.models.fields.CharField'
,
[],
{
'db_index'
:
'True'
,
'max_length'
:
'16'
,
'blank'
:
'True'
}),
'salutation'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'50'
,
'blank'
:
'True'
}),
'state'
:
(
'django.db.models.fields.CharField'
,
[],
{
'db_index'
:
'True'
,
'max_length'
:
'20'
,
'blank'
:
'True'
}),
'suffix'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'blank'
:
'True'
}),
'updated_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now'
:
'True'
,
'db_index'
:
'True'
,
'blank'
:
'True'
}),
'user'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'default'
:
'None'
,
'to'
:
"orm['auth.User']"
,
'unique'
:
'True'
}),
'user_updated_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'db_index'
:
'True'
})
},
'student.userprofile'
:
{
'Meta'
:
{
'object_name'
:
'UserProfile'
,
'db_table'
:
"'auth_userprofile'"
},
'courseware'
:
(
'django.db.models.fields.CharField'
,
[],
{
'default'
:
"'course.xml'"
,
'max_length'
:
'255'
,
'blank'
:
'True'
}),
'gender'
:
(
'django.db.models.fields.CharField'
,
[],
{
'db_index'
:
'True'
,
'max_length'
:
'6'
,
'null'
:
'True'
,
'blank'
:
'True'
}),
'goals'
:
(
'django.db.models.fields.TextField'
,
[],
{
'null'
:
'True'
,
'blank'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'language'
:
(
'django.db.models.fields.CharField'
,
[],
{
'db_index'
:
'True'
,
'max_length'
:
'255'
,
'blank'
:
'True'
}),
'level_of_education'
:
(
'django.db.models.fields.CharField'
,
[],
{
'db_index'
:
'True'
,
'max_length'
:
'6'
,
'null'
:
'True'
,
'blank'
:
'True'
}),
'location'
:
(
'django.db.models.fields.CharField'
,
[],
{
'db_index'
:
'True'
,
'max_length'
:
'255'
,
'blank'
:
'True'
}),
'mailing_address'
:
(
'django.db.models.fields.TextField'
,
[],
{
'null'
:
'True'
,
'blank'
:
'True'
}),
'meta'
:
(
'django.db.models.fields.TextField'
,
[],
{
'blank'
:
'True'
}),
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'db_index'
:
'True'
,
'max_length'
:
'255'
,
'blank'
:
'True'
}),
'user'
:
(
'django.db.models.fields.related.OneToOneField'
,
[],
{
'related_name'
:
"'profile'"
,
'unique'
:
'True'
,
'to'
:
"orm['auth.User']"
}),
'year_of_birth'
:
(
'django.db.models.fields.IntegerField'
,
[],
{
'db_index'
:
'True'
,
'null'
:
'True'
,
'blank'
:
'True'
})
},
'student.usertestgroup'
:
{
'Meta'
:
{
'object_name'
:
'UserTestGroup'
},
'description'
:
(
'django.db.models.fields.TextField'
,
[],
{
'blank'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'32'
,
'db_index'
:
'True'
}),
'users'
:
(
'django.db.models.fields.related.ManyToManyField'
,
[],
{
'to'
:
"orm['auth.User']"
,
'db_index'
:
'True'
,
'symmetrical'
:
'False'
})
}
}
complete_apps
=
[
'student'
]
\ No newline at end of file
common/djangoapps/student/migrations/0021_remove_askbot.py.old
0 → 100644
View file @
200493a5
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
ASKBOT_AUTH_USER_COLUMNS = (
'website',
'about',
'gold',
'email_isvalid',
'real_name',
'location',
'reputation',
'gravatar',
'bronze',
'last_seen',
'silver',
'questions_per_page',
'new_response_count',
'seen_response_count',
)
class Migration(SchemaMigration):
def forwards(self, orm):
"Kill the askbot"
# For MySQL, we're batching the alters together for performance reasons
if db.backend_name == 'mysql':
drops = ["drop `{0}`".format(col) for col in ASKBOT_AUTH_USER_COLUMNS]
statement = "alter table `auth_user` {0};".format(", ".join(drops))
db.execute(statement)
else:
for column in ASKBOT_AUTH_USER_COLUMNS:
db.delete_column('auth_user', column)
def backwards(self, orm):
raise RuntimeError("Cannot reverse this migration: there's no going back to Askbot.")
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'student.courseenrollment': {
'Meta': {'unique_together': "(('user', 'course_id'),)", 'object_name': 'CourseEnrollment'},
'course_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'student.pendingemailchange': {
'Meta': {'object_name': 'PendingEmailChange'},
'activation_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32', 'db_index': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'new_email': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'})
},
'student.pendingnamechange': {
'Meta': {'object_name': 'PendingNameChange'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'new_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'rationale': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'})
},
'student.registration': {
'Meta': {'object_name': 'Registration', 'db_table': "'auth_registration'"},
'activation_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32', 'db_index': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'})
},
'student.testcenteruser': {
'Meta': {'object_name': 'TestCenterUser'},
'address_1': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'address_2': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'}),
'address_3': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'}),
'candidate_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'db_index': 'True'}),
'city': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}),
'client_candidate_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}),
'company_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'country': ('django.db.models.fields.CharField', [], {'max_length': '3', 'db_index': 'True'}),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
'extension': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '8', 'blank': 'True'}),
'fax': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}),
'fax_country_code': ('django.db.models.fields.CharField', [], {'max_length': '3', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'db_index': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}),
'middle_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'phone': ('django.db.models.fields.CharField', [], {'max_length': '35'}),
'phone_country_code': ('django.db.models.fields.CharField', [], {'max_length': '3', 'db_index': 'True'}),
'postal_code': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '16', 'blank': 'True'}),
'salutation': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'state': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '20', 'blank': 'True'}),
'suffix': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['auth.User']", 'unique': 'True'}),
'user_updated_at': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'})
},
'student.userprofile': {
'Meta': {'object_name': 'UserProfile', 'db_table': "'auth_userprofile'"},
'courseware': ('django.db.models.fields.CharField', [], {'default': "'course.xml'", 'max_length': '255', 'blank': 'True'}),
'gender': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '6', 'null': 'True', 'blank': 'True'}),
'goals': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'language': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}),
'level_of_education': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '6', 'null': 'True', 'blank': 'True'}),
'location': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}),
'mailing_address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'meta': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"}),
'year_of_birth': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'})
},
'student.usertestgroup': {
'Meta': {'object_name': 'UserTestGroup'},
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}),
'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.User']", 'db_index': 'True', 'symmetrical': 'False'})
}
}
complete_apps = ['student']
common/djangoapps/student/models.py
View file @
200493a5
...
@@ -262,6 +262,24 @@ class CourseEnrollment(models.Model):
...
@@ -262,6 +262,24 @@ class CourseEnrollment(models.Model):
return
"[CourseEnrollment]
%
s:
%
s (
%
s)"
%
(
self
.
user
,
self
.
course_id
,
self
.
created
)
return
"[CourseEnrollment]
%
s:
%
s (
%
s)"
%
(
self
.
user
,
self
.
course_id
,
self
.
created
)
class
CourseEnrollmentAllowed
(
models
.
Model
):
"""
Table of users (specified by email address strings) who are allowed to enroll in a specified course.
The user may or may not (yet) exist. Enrollment by users listed in this table is allowed
even if the enrollment time window is past.
"""
email
=
models
.
CharField
(
max_length
=
255
,
db_index
=
True
)
course_id
=
models
.
CharField
(
max_length
=
255
,
db_index
=
True
)
created
=
models
.
DateTimeField
(
auto_now_add
=
True
,
null
=
True
,
db_index
=
True
)
class
Meta
:
unique_together
=
((
'email'
,
'course_id'
),
)
def
__unicode__
(
self
):
return
"[CourseEnrollmentAllowed]
%
s:
%
s (
%
s)"
%
(
self
.
email
,
self
.
course_id
,
self
.
created
)
@receiver
(
post_save
,
sender
=
CourseEnrollment
)
@receiver
(
post_save
,
sender
=
CourseEnrollment
)
def
assign_default_role
(
sender
,
instance
,
**
kwargs
):
def
assign_default_role
(
sender
,
instance
,
**
kwargs
):
if
instance
.
user
.
is_staff
:
if
instance
.
user
.
is_staff
:
...
...
lms/djangoapps/instructor/views.py
View file @
200493a5
...
@@ -2,8 +2,10 @@
...
@@ -2,8 +2,10 @@
from
collections
import
defaultdict
from
collections
import
defaultdict
import
csv
import
csv
import
json
import
logging
import
logging
import
os
import
os
import
requests
import
urllib
import
urllib
from
django.conf
import
settings
from
django.conf
import
settings
...
@@ -20,7 +22,7 @@ from courseware.courses import get_course_with_access
...
@@ -20,7 +22,7 @@ from courseware.courses import get_course_with_access
from
django_comment_client.models
import
Role
,
FORUM_ROLE_ADMINISTRATOR
,
FORUM_ROLE_MODERATOR
,
FORUM_ROLE_COMMUNITY_TA
from
django_comment_client.models
import
Role
,
FORUM_ROLE_ADMINISTRATOR
,
FORUM_ROLE_MODERATOR
,
FORUM_ROLE_COMMUNITY_TA
from
django_comment_client.utils
import
has_forum_access
from
django_comment_client.utils
import
has_forum_access
from
psychometrics
import
psychoanalyze
from
psychometrics
import
psychoanalyze
from
student.models
import
CourseEnrollment
from
student.models
import
CourseEnrollment
,
CourseEnrollmentAllowed
from
xmodule.course_module
import
CourseDescriptor
from
xmodule.course_module
import
CourseDescriptor
from
xmodule.modulestore
import
Location
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
...
@@ -125,7 +127,7 @@ def instructor_dashboard(request, course_id):
...
@@ -125,7 +127,7 @@ def instructor_dashboard(request, course_id):
except
Exception
as
err
:
except
Exception
as
err
:
msg
+=
'<br/><p>Error: {0}</p>'
.
format
(
escape
(
err
))
msg
+=
'<br/><p>Error: {0}</p>'
.
format
(
escape
(
err
))
if
action
==
'Dump list of enrolled students'
:
if
action
==
'Dump list of enrolled students'
or
action
==
'List enrolled students'
:
log
.
debug
(
action
)
log
.
debug
(
action
)
datatable
=
get_student_grade_summary_data
(
request
,
course
,
course_id
,
get_grades
=
False
)
datatable
=
get_student_grade_summary_data
(
request
,
course
,
course_id
,
get_grades
=
False
)
datatable
[
'title'
]
=
'List of students enrolled in {0}'
.
format
(
course_id
)
datatable
[
'title'
]
=
'List of students enrolled in {0}'
.
format
(
course_id
)
...
@@ -258,6 +260,70 @@ def instructor_dashboard(request, course_id):
...
@@ -258,6 +260,70 @@ def instructor_dashboard(request, course_id):
{},
page
=
'idashboard'
)
{},
page
=
'idashboard'
)
#----------------------------------------
#----------------------------------------
# enrollment
elif
action
==
'List students who may enroll but may not have yet signed up'
:
ceaset
=
CourseEnrollmentAllowed
.
objects
.
filter
(
course_id
=
course_id
)
datatable
=
{
'header'
:
[
'StudentEmail'
]}
datatable
[
'data'
]
=
[[
x
.
email
]
for
x
in
ceaset
]
datatable
[
'title'
]
=
action
elif
action
==
'Enroll student'
:
student
=
request
.
POST
.
get
(
'enstudent'
,
''
)
datatable
=
{}
try
:
nce
=
CourseEnrollment
(
user
=
User
.
objects
.
get
(
email
=
student
),
course_id
=
course_id
)
nce
.
save
()
msg
+=
"Enrolled student with email '
%
s'"
%
student
except
Exception
as
err
:
msg
+=
"Error! Failed to enroll student with email '
%
s'
\n
"
%
student
msg
+=
str
(
err
)
+
'
\n
'
elif
action
==
'Un-enroll student'
:
student
=
request
.
POST
.
get
(
'enstudent'
,
''
)
datatable
=
{}
try
:
nce
=
CourseEnrollment
.
objects
.
get
(
user
=
User
.
objects
.
get
(
email
=
student
),
course_id
=
course_id
)
nce
.
delete
()
msg
+=
"Un-enrolled student with email '
%
s'"
%
student
except
Exception
as
err
:
msg
+=
"Error! Failed to un-enroll student with email '
%
s'
\n
"
%
student
msg
+=
str
(
err
)
+
'
\n
'
elif
action
==
'Un-enroll ALL students'
:
ret
=
_do_enroll_students
(
course
,
course_id
,
''
,
overload
=
True
)
datatable
=
ret
[
'datatable'
]
elif
action
==
'Enroll multiple students'
:
students
=
request
.
POST
.
get
(
'enroll_multiple'
,
''
)
ret
=
_do_enroll_students
(
course
,
course_id
,
students
)
datatable
=
ret
[
'datatable'
]
elif
action
==
'List sections available in remote gradebook'
:
msg2
,
datatable
=
_do_remote_gradebook
(
course
,
'get-sections'
)
msg
+=
msg2
elif
action
in
[
'List students in section in remote gradebook'
,
'Overload enrollment list using remote gradebook'
,
'Merge enrollment list with remote gradebook'
]:
section
=
request
.
POST
.
get
(
'gradebook_section'
,
''
)
msg2
,
datatable
=
_do_remote_gradebook
(
course
,
'get-membership'
,
dict
(
section
=
section
)
)
msg
+=
msg2
if
not
'List'
in
action
:
students
=
','
.
join
([
x
[
'email'
]
for
x
in
datatable
[
'retdata'
]])
overload
=
'Overload'
in
action
ret
=
_do_enroll_students
(
course
,
course_id
,
students
,
overload
=
overload
)
datatable
=
ret
[
'datatable'
]
#----------------------------------------
# psychometrics
# psychometrics
elif
action
==
'Generate Histogram and IRT Plot'
:
elif
action
==
'Generate Histogram and IRT Plot'
:
...
@@ -270,9 +336,9 @@ def instructor_dashboard(request, course_id):
...
@@ -270,9 +336,9 @@ def instructor_dashboard(request, course_id):
problems
=
psychoanalyze
.
problems_with_psychometric_data
(
course_id
)
problems
=
psychoanalyze
.
problems_with_psychometric_data
(
course_id
)
#----------------------------------------
#----------------------------------------
# context for rendering
# context for rendering
context
=
{
'course'
:
course
,
context
=
{
'course'
:
course
,
'staff_access'
:
True
,
'staff_access'
:
True
,
'admin_access'
:
request
.
user
.
is_staff
,
'admin_access'
:
request
.
user
.
is_staff
,
...
@@ -285,16 +351,65 @@ def instructor_dashboard(request, course_id):
...
@@ -285,16 +351,65 @@ def instructor_dashboard(request, course_id):
'plots'
:
plots
,
# psychometrics
'plots'
:
plots
,
# psychometrics
'course_errors'
:
modulestore
()
.
get_item_errors
(
course
.
location
),
'course_errors'
:
modulestore
()
.
get_item_errors
(
course
.
location
),
'djangopid'
:
os
.
getpid
(),
'djangopid'
:
os
.
getpid
(),
'mitx_version'
:
getattr
(
settings
,
'MITX_VERSION_STRING'
,
''
)
}
}
return
render_to_response
(
'courseware/instructor_dashboard.html'
,
context
)
return
render_to_response
(
'courseware/instructor_dashboard.html'
,
context
)
def
_do_remote_gradebook
(
course
,
action
,
args
=
None
):
'''
Perform remote gradebook action. Returns msg, datatable.
'''
rg
=
course
.
metadata
.
get
(
'remote_gradebook'
,
''
)
if
not
rg
:
msg
=
"No remote gradebook defined in course metadata"
return
msg
,
{}
rgurl
=
settings
.
MITX_FEATURES
.
get
(
'REMOTE_GRADEBOOK_URL'
,
''
)
if
not
rgurl
:
msg
=
"No remote gradebook url defined in settings.MITX_FEATURES"
return
msg
,
{}
rgname
=
rg
.
get
(
'name'
,
''
)
if
not
rgname
:
msg
=
"No gradebook name defined in course remote_gradebook metadata"
return
msg
,
{}
if
args
is
None
:
args
=
{}
data
=
dict
(
submit
=
action
,
gradebook
=
rgname
)
data
.
update
(
args
)
try
:
resp
=
requests
.
post
(
rgurl
,
data
=
data
,
verify
=
False
)
retdict
=
json
.
loads
(
resp
.
content
)
except
Exception
as
err
:
msg
=
"Failed to communicate with gradebook server at
%
s<br/>"
%
rgurl
msg
+=
"Error:
%
s"
%
err
msg
+=
"<br/>resp=
%
s"
%
resp
.
content
msg
+=
"<br/>data=
%
s"
%
data
return
msg
,
{}
msg
=
'<pre>
%
s</pre>'
%
retdict
[
'msg'
]
.
replace
(
'
\n
'
,
'<br/>'
)
retdata
=
retdict
[
'data'
]
if
retdata
:
datatable
=
{
'header'
:
retdata
[
0
]
.
keys
()}
datatable
[
'data'
]
=
[
x
.
values
()
for
x
in
retdata
]
datatable
[
'title'
]
=
'Remote gradebook response for
%
s'
%
action
datatable
[
'retdata'
]
=
retdata
else
:
datatable
=
{}
return
msg
,
datatable
def
_list_course_forum_members
(
course_id
,
rolename
,
datatable
):
def
_list_course_forum_members
(
course_id
,
rolename
,
datatable
):
'''
'''
Fills in datatable with forum membership information, for a given role,
Fills in datatable with forum membership information, for a given role,
so that it will be displayed on instructor dashboard.
so that it will be displayed on instructor dashboard.
course_ID =
course's ID string
course_ID =
the ID string for a course
rolename = one of "Administrator", "Moderator", "Community TA"
rolename = one of "Administrator", "Moderator", "Community TA"
Returns message status string to append to displayed message, if role is unknown.
Returns message status string to append to displayed message, if role is unknown.
...
@@ -455,6 +570,68 @@ def grade_summary(request, course_id):
...
@@ -455,6 +570,68 @@ def grade_summary(request, course_id):
return
render_to_response
(
'courseware/grade_summary.html'
,
context
)
return
render_to_response
(
'courseware/grade_summary.html'
,
context
)
def
_do_enroll_students
(
course
,
course_id
,
students
,
overload
=
False
):
"""Do the actual work of enrolling multiple students, presented as a string
of emails separated by commas or returns"""
ns
=
[
x
.
split
(
'
\n
'
)
for
x
in
students
.
split
(
','
)]
new_students
=
[
item
for
sublist
in
ns
for
item
in
sublist
]
new_students
=
[
str
(
s
.
strip
())
for
s
in
new_students
]
new_students_lc
=
[
x
.
lower
()
for
x
in
new_students
]
if
''
in
new_students
:
new_students
.
remove
(
''
)
status
=
dict
([
x
,
'unprocessed'
]
for
x
in
new_students
)
if
overload
:
# delete all but staff
todelete
=
CourseEnrollment
.
objects
.
filter
(
course_id
=
course_id
)
for
ce
in
todelete
:
if
not
has_access
(
ce
.
user
,
course
,
'staff'
)
and
ce
.
user
.
email
.
lower
()
not
in
new_students_lc
:
status
[
ce
.
user
.
email
]
=
'deleted'
ce
.
delete
()
else
:
status
[
ce
.
user
.
email
]
=
'is staff'
ceaset
=
CourseEnrollmentAllowed
.
objects
.
filter
(
course_id
=
course_id
)
for
cea
in
ceaset
:
status
[
cea
.
email
]
=
'removed from pending enrollment list'
ceaset
.
delete
()
for
student
in
new_students
:
try
:
user
=
User
.
objects
.
get
(
email
=
student
)
except
User
.
DoesNotExist
:
# user not signed up yet, put in pending enrollment allowed table
if
CourseEnrollmentAllowed
.
objects
.
filter
(
email
=
student
,
course_id
=
course_id
):
status
[
student
]
=
'user does not exist, enrollment already allowed, pending'
continue
cea
=
CourseEnrollmentAllowed
(
email
=
student
,
course_id
=
course_id
)
cea
.
save
()
status
[
student
]
=
'user does not exist, enrollment allowed, pending'
continue
if
CourseEnrollment
.
objects
.
filter
(
user
=
user
,
course_id
=
course_id
):
status
[
student
]
=
'already enrolled'
continue
try
:
nce
=
CourseEnrollment
(
user
=
user
,
course_id
=
course_id
)
nce
.
save
()
status
[
student
]
=
'added'
except
:
status
[
student
]
=
'rejected'
datatable
=
{
'header'
:
[
'StudentEmail'
,
'action'
]}
datatable
[
'data'
]
=
[[
x
,
status
[
x
]]
for
x
in
status
]
datatable
[
'title'
]
=
'Enrollment of students'
def
sf
(
stat
):
return
[
x
for
x
in
status
if
status
[
x
]
==
stat
]
data
=
dict
(
added
=
sf
(
'added'
),
rejected
=
sf
(
'rejected'
)
+
sf
(
'exists'
),
deleted
=
sf
(
'deleted'
),
datatable
=
datatable
)
return
data
@ensure_csrf_cookie
@ensure_csrf_cookie
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
def
enroll_students
(
request
,
course_id
):
def
enroll_students
(
request
,
course_id
):
...
@@ -473,22 +650,10 @@ def enroll_students(request, course_id):
...
@@ -473,22 +650,10 @@ def enroll_students(request, course_id):
course
=
get_course_with_access
(
request
.
user
,
course_id
,
'staff'
)
course
=
get_course_with_access
(
request
.
user
,
course_id
,
'staff'
)
existing_students
=
[
ce
.
user
.
email
for
ce
in
CourseEnrollment
.
objects
.
filter
(
course_id
=
course_id
)]
existing_students
=
[
ce
.
user
.
email
for
ce
in
CourseEnrollment
.
objects
.
filter
(
course_id
=
course_id
)]
if
'new_students'
in
request
.
POST
:
new_students
=
request
.
POST
.
get
(
'new_students'
)
new_students
=
request
.
POST
[
'new_students'
]
.
split
(
'
\n
'
)
ret
=
_do_enroll_students
(
course
,
course_id
,
new_students
)
else
:
added_students
=
ret
[
'added'
]
new_students
=
[]
rejected_students
=
ret
[
'rejected'
]
new_students
=
[
s
.
strip
()
for
s
in
new_students
]
added_students
=
[]
rejected_students
=
[]
for
student
in
new_students
:
try
:
nce
=
CourseEnrollment
(
user
=
User
.
objects
.
get
(
email
=
student
),
course_id
=
course_id
)
nce
.
save
()
added_students
.
append
(
student
)
except
:
rejected_students
.
append
(
student
)
return
render_to_response
(
"enroll_students.html"
,
{
'course'
:
course_id
,
return
render_to_response
(
"enroll_students.html"
,
{
'course'
:
course_id
,
'existing_students'
:
existing_students
,
'existing_students'
:
existing_students
,
...
...
lms/envs/dev.py
View file @
200493a5
...
@@ -102,6 +102,10 @@ SUBDOMAIN_BRANDING = {
...
@@ -102,6 +102,10 @@ SUBDOMAIN_BRANDING = {
COMMENTS_SERVICE_KEY
=
"PUT_YOUR_API_KEY_HERE"
COMMENTS_SERVICE_KEY
=
"PUT_YOUR_API_KEY_HERE"
################################# mitx revision string #####################
MITX_VERSION_STRING
=
os
.
popen
(
'cd
%
s; git describe'
%
REPO_ROOT
)
.
read
()
.
strip
()
################################# Staff grading config #####################
################################# Staff grading config #####################
STAFF_GRADING_INTERFACE
=
{
STAFF_GRADING_INTERFACE
=
{
...
...
lms/templates/courseware/instructor_dashboard.html
View file @
200493a5
...
@@ -57,10 +57,13 @@ function goto( mode)
...
@@ -57,10 +57,13 @@ function goto( mode)
<a
href=
"#"
onclick=
"goto('Psychometrics');"
class=
"${modeflag.get('Psychometrics')}"
>
Psychometrics
</a>
|
<a
href=
"#"
onclick=
"goto('Psychometrics');"
class=
"${modeflag.get('Psychometrics')}"
>
Psychometrics
</a>
|
%endif
%endif
<a
href=
"#"
onclick=
"goto('Admin');"
class=
"${modeflag.get('Admin')}"
>
Admin
</a>
|
<a
href=
"#"
onclick=
"goto('Admin');"
class=
"${modeflag.get('Admin')}"
>
Admin
</a>
|
<a
href=
"#"
onclick=
"goto('Forum Admin');"
class=
"${modeflag.get('Forum Admin')}"
>
Forum Admin
</a>
]
<a
href=
"#"
onclick=
"goto('Forum Admin');"
class=
"${modeflag.get('Forum Admin')}"
>
Forum Admin
</a>
|
<a
href=
"#"
onclick=
"goto('Enrollment');"
class=
"${modeflag.get('Enrollment')}"
>
Enrollment
</a>
]
</h2>
</h2>
<div
style=
"text-align:right"
id=
"djangopid"
>
${djangopid}
</div>
<div
style=
"text-align:right"
><span
id=
"djangopid"
>
${djangopid}
</span>
|
<span
id=
"mitxver"
>
${mitx_version}
</span></div>
<form
name=
"idashform"
method=
"POST"
>
<form
name=
"idashform"
method=
"POST"
>
<input
type=
"hidden"
name=
"csrfmiddlewaretoken"
value=
"${ csrf_token }"
>
<input
type=
"hidden"
name=
"csrfmiddlewaretoken"
value=
"${ csrf_token }"
>
...
@@ -163,10 +166,52 @@ function goto( mode)
...
@@ -163,10 +166,52 @@ function goto( mode)
%endif
%endif
%endif
%endif
##-----------------------------------------------------------------------------
%if modeflag.get('Enrollment'):
<hr
width=
"40%"
style=
"align:left"
>
<p>
<input
type=
"submit"
name=
"action"
value=
"List enrolled students"
>
<input
type=
"submit"
name=
"action"
value=
"List students who may enroll but may not have yet signed up"
>
<p>
Student Email:
<input
type=
"text"
name=
"enstudent"
>
<input
type=
"submit"
name=
"action"
value=
"Un-enroll student"
>
<input
type=
"submit"
name=
"action"
value=
"Enroll student"
>
<input
type=
"submit"
name=
"action"
value=
"Un-enroll ALL students"
>
<hr
width=
"40%"
style=
"align:left"
>
%if settings.MITX_FEATURES.get('REMOTE_GRADEBOOK_URL','') and instructor_access:
<
%
rg =
course.metadata.get('remote_gradebook',{})
%
>
<p>
Pull enrollment from remote gradebook
</p>
<ul>
<li>
Gradebook name:
<input
type=
"text"
name=
"gradebook_name"
size=
40
value=
"${rg.get('name','')}"
></li>
<li>
Section:
<input
type=
"text"
name=
"gradebook_section"
size=
40
value=
"${rg.get('section','')}"
></li>
</ul>
<input
type=
"submit"
name=
"action"
value=
"List sections available in remote gradebook"
>
<input
type=
"submit"
name=
"action"
value=
"List students in section in remote gradebook"
>
<input
type=
"submit"
name=
"action"
value=
"Overload enrollment list using remote gradebook"
>
<input
type=
"submit"
name=
"action"
value=
"Merge enrollment list with remote gradebook"
>
<hr
width=
"40%"
style=
"align:left"
>
%endif
<p>
Add students: enter emails, separated by returns or commas;
</p>
<textarea
rows=
"6"
cols=
"70"
name=
"enroll_multiple"
></textarea>
<input
type=
"submit"
name=
"action"
value=
"Enroll multiple students"
>
%endif
##-----------------------------------------------------------------------------
</form>
</form>
##-----------------------------------------------------------------------------
##-----------------------------------------------------------------------------
%if modeflag.get('Psychometrics') is None:
##-----------------------------------------------------------------------------
%if datatable and modeflag.get('Psychometrics') is None:
<br/>
<br/>
<br/>
<br/>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment