37
37
from ivle.webapp.base.xhtml import XHTMLView
38
38
from ivle.webapp.base.plugins import ViewPlugin, MediaPlugin
39
from ivle.webapp import ApplicationRoot
39
from ivle.webapp.errors import NotFound
41
41
from ivle.database import Subject, Semester, Offering, Enrolment, User,\
42
42
ProjectSet, Project, ProjectSubmission
46
46
from ivle.webapp.admin.projectservice import ProjectSetRESTView,\
48
48
from ivle.webapp.admin.offeringservice import OfferingRESTView
49
from ivle.webapp.admin.publishing import (root_to_subject,
50
subject_to_offering, offering_to_projectset, offering_to_project,
51
subject_url, offering_url, projectset_url, project_url)
52
from ivle.webapp.admin.breadcrumbs import (SubjectBreadcrumb,
53
OfferingBreadcrumb, UserBreadcrumb, ProjectBreadcrumb)
54
from ivle.webapp.groups import GroupsView
56
51
class SubjectsView(XHTMLView):
57
52
'''The view of the list of subjects.'''
99
94
user = formencode.All(NoEnrolmentValidator(), UserValidator())
102
class EnrolmentsView(XHTMLView):
103
"""A page which displays all users enrolled in an offering."""
104
template = 'templates/enrolments.html'
107
def populate(self, req, ctx):
108
ctx['offering'] = self.context
110
97
class EnrolView(XHTMLView):
111
98
"""A form to enrol a user in an offering."""
112
99
template = 'templates/enrol.html'
114
101
permission = 'edit'
103
def __init__(self, req, subject, year, semester):
104
"""Find the given offering by subject, year and semester."""
105
self.context = req.store.find(Offering,
106
Offering.subject_id == Subject.id,
107
Subject.short_name == subject,
108
Offering.semester_id == Semester.id,
109
Semester.year == year,
110
Semester.semester == semester).one()
116
115
def filter(self, stream, ctx):
117
116
return stream | HTMLFormFiller(data=ctx['data'])
141
140
template = 'templates/offering_projects.html'
142
141
permission = 'edit'
144
def __init__(self, req, subject, year, semester):
145
self.context = req.store.find(Offering,
146
Offering.subject_id == Subject.id,
147
Subject.short_name == subject,
148
Offering.semester_id == Semester.id,
149
Semester.year == year,
150
Semester.semester == semester).one()
155
def project_url(self, projectset, project):
156
return "/subjects/%s/%s/%s/+projects/%s" % (
157
self.context.subject.short_name,
158
self.context.semester.year,
159
self.context.semester.semester,
163
def new_project_url(self, projectset):
164
return "/api/subjects/" + self.context.subject.short_name + "/" +\
165
self.context.semester.year + "/" + \
166
self.context.semester.semester + "/+projectsets/" +\
167
str(projectset.id) + "/+projects/+new"
145
169
def populate(self, req, ctx):
146
170
self.plugin_styles[Plugin] = ["project.css"]
147
171
self.plugin_scripts[Plugin] = ["project.js"]
149
172
ctx['offering'] = self.context
150
173
ctx['projectsets'] = []
151
ctx['OfferingRESTView'] = OfferingRESTView
153
175
#Open the projectset Fragment, and render it for inclusion
154
176
#into the ProjectSets page
163
185
for projectset in self.context.project_sets:
164
186
settmpl = loader.load(set_fragment)
165
187
setCtx = Context()
167
188
setCtx['projectset'] = projectset
189
setCtx['new_project_url'] = self.new_project_url(projectset)
168
190
setCtx['projects'] = []
169
setCtx['GroupsView'] = GroupsView
170
setCtx['ProjectSetRESTView'] = ProjectSetRESTView
172
192
for project in projectset.projects:
173
193
projecttmpl = loader.load(project_fragment)
174
194
projectCtx = Context()
175
projectCtx['req'] = req
176
195
projectCtx['project'] = project
196
projectCtx['project_url'] = self.project_url(projectset, project)
178
198
setCtx['projects'].append(
179
199
projecttmpl.generate(projectCtx))
187
207
permission = "edit"
210
def __init__(self, req, subject, year, semester, project):
211
self.context = req.store.find(Project,
212
Project.short_name == project,
213
Project.project_set_id == ProjectSet.id,
214
ProjectSet.offering_id == Offering.id,
215
Offering.semester_id == Semester.id,
216
Semester.year == year,
217
Semester.semester == semester,
218
Offering.subject_id == Subject.id,
219
Subject.short_name == subject).one()
220
if self.context is None:
190
223
def build_subversion_url(self, svnroot, submission):
191
224
princ = submission.assessed.principal
214
247
ctx['project'] = self.context
215
248
ctx['user'] = req.user
217
class OfferingEnrolmentSet(object):
218
def __init__(self, offering):
219
self.offering = offering
221
250
class Plugin(ViewPlugin, MediaPlugin):
222
forward_routes = (root_to_subject, subject_to_offering,
223
offering_to_project, offering_to_projectset)
224
reverse_routes = (subject_url, offering_url, projectset_url, project_url)
226
views = [(ApplicationRoot, ('subjects', '+index'), SubjectsView),
227
(Offering, ('+enrolments', '+index'), EnrolmentsView),
228
(Offering, ('+enrolments', '+new'), EnrolView),
229
(Offering, ('+projects', '+index'), OfferingProjectsView),
230
(Project, '+index', ProjectView),
232
(Offering, ('+projectsets', '+new'), OfferingRESTView, 'api'),
233
(ProjectSet, ('+projects', '+new'), ProjectSetRESTView, 'api'),
234
(Project, '+index', ProjectRESTView, 'api'),
237
breadcrumbs = {Subject: SubjectBreadcrumb,
238
Offering: OfferingBreadcrumb,
239
User: UserBreadcrumb,
240
Project: ProjectBreadcrumb,
252
('subjects/', SubjectsView),
253
('subjects/:subject/:year/:semester/+enrolments/+new', EnrolView),
254
('subjects/:subject/:year/:semester/+projects', OfferingProjectsView),
255
('subjects/:subject/:year/:semester/+projects/:project', ProjectView),
257
('api/subjects/:subject/:year/:semester/+projectsets/+new',
259
('api/subjects/:subject/:year/:semester/+projectsets/:projectset/+projects/+new',
261
('api/subjects/:subject/:year/:semester/+projects/:project',
244
267
('subjects', 'Subjects',