~azzar1/unity/add-show-desktop-key

621 by mattgiuca
Added 2 new apps: home and subjects. Both fairly incomplete, just a basic
1
# IVLE
2
# Copyright (C) 2007-2008 The University of Melbourne
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
18
# App: subjects
19
# Author: Matt Giuca
20
# Date: 29/2/2008
21
22
# This is an IVLE application.
23
# A sample / testing application for IVLE.
24
627 by mattgiuca
subjects: Now presents a top-level subjects menu (same as tutorials).
25
import os
1165.3.61 by William Grant
Provide a Subversion command to grab each submission.
26
import os.path
627 by mattgiuca
subjects: Now presents a top-level subjects menu (same as tutorials).
27
import urllib
1165.3.61 by William Grant
Provide a Subversion command to grab each submission.
28
import urlparse
627 by mattgiuca
subjects: Now presents a top-level subjects menu (same as tutorials).
29
import cgi
30
1294.2.52 by William Grant
Port subject-related views to object traversal.
31
from storm.locals import Desc, Store
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
32
import genshi
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
33
from genshi.filters import HTMLFormFiller
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
34
from genshi.template import Context, TemplateLoader
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
35
import formencode
1125 by William Grant
Rework ivle.webapp.admin.subjects#SubjectsView to split offerings nicely by
36
1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
37
from ivle.webapp.base.xhtml import XHTMLView
1099.1.115 by William Grant
Add tabs to the new framework. Move the app icons into the apps themselves.
38
from ivle.webapp.base.plugins import ViewPlugin, MediaPlugin
1294.2.52 by William Grant
Port subject-related views to object traversal.
39
from ivle.webapp import ApplicationRoot
1165.3.9 by Nick Chadwick
merge from trunk
40
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
41
from ivle.database import Subject, Semester, Offering, Enrolment, User,\
1165.3.8 by Nick Chadwick
Added a total submissions and total assesseds to the project view
42
                          ProjectSet, Project, ProjectSubmission
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
43
from ivle import util
1165.3.14 by William Grant
Improve ProjectView's template substantially.
44
import ivle.date
621 by mattgiuca
Added 2 new apps: home and subjects. Both fairly incomplete, just a basic
45
1375.1.2 by William Grant
Remove ProjectRESTView, which did nothing and was unused.
46
from ivle.webapp.admin.projectservice import ProjectSetRESTView
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
47
from ivle.webapp.admin.offeringservice import OfferingRESTView
1294.3.2 by William Grant
Router->Publisher
48
from ivle.webapp.admin.publishing import (root_to_subject,
1294.2.70 by William Grant
Split out ivle.webapp.admin's routes into annotated functions in ivle.webapp.traversal.
49
            subject_to_offering, offering_to_projectset, offering_to_project,
50
            subject_url, offering_url, projectset_url, project_url)
1294.2.96 by William Grant
Add a UserBreadcrumb.
51
from ivle.webapp.admin.breadcrumbs import (SubjectBreadcrumb,
1294.2.98 by William Grant
Add a ProjectBreadcrumb.
52
            OfferingBreadcrumb, UserBreadcrumb, ProjectBreadcrumb)
1358 by William Grant
Use the publishing framework to generate URLs to projectsets.
53
from ivle.webapp.groups import GroupsView
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
54
1099.1.20 by William Grant
ivle.webapp.admin.subject: Port www/apps/subjects to new framework.
55
class SubjectsView(XHTMLView):
56
    '''The view of the list of subjects.'''
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
57
    template = 'templates/subjects.html'
1116 by William Grant
Move the old tutorial views into the 'subjects' tab, so they get the right
58
    tab = 'subjects'
1099.1.20 by William Grant
ivle.webapp.admin.subject: Port www/apps/subjects to new framework.
59
1099.1.110 by William Grant
Implement an authorization system in the new framework. This breaks the REST
60
    def authorize(self, req):
1138 by William Grant
SubjectsView now tells users if they have no enrolments.
61
        return req.user is not None
1099.1.110 by William Grant
Implement an authorization system in the new framework. This breaks the REST
62
1099.1.20 by William Grant
ivle.webapp.admin.subject: Port www/apps/subjects to new framework.
63
    def populate(self, req, ctx):
1139 by William Grant
Show group administration links on SubjectsView where privileges allow it.
64
        ctx['user'] = req.user
1125 by William Grant
Rework ivle.webapp.admin.subjects#SubjectsView to split offerings nicely by
65
        ctx['semesters'] = []
66
        for semester in req.store.find(Semester).order_by(Desc(Semester.year),
67
                                                     Desc(Semester.semester)):
1372 by Matt Giuca
admin/subject: Admin users now see all offerings in the system, not just the ones they are enrolled in.
68
            if req.user.admin:
69
                # For admins, show all subjects in the system
70
                offerings = list(semester.offerings.find())
71
            else:
72
                offerings = [enrolment.offering for enrolment in
1371 by Matt Giuca
admin/subject: Now sends a list of offerings the user is enrolled in to the Genshi template, rather than a list of enrolment objects (of which only the offering is observed). This allows us to send non-enrolment offerings to the template.
73
                                    semester.enrolments.find(user=req.user)]
74
            if len(offerings):
75
                ctx['semesters'].append((semester, offerings))
1099.1.20 by William Grant
ivle.webapp.admin.subject: Port www/apps/subjects to new framework.
76
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
77
78
class UserValidator(formencode.FancyValidator):
79
    """A FormEncode validator that turns a username into a user.
80
81
    The state must have a 'store' attribute, which is the Storm store
82
    to use."""
83
    def _to_python(self, value, state):
84
        user = User.get_by_login(state.store, value)
85
        if user:
86
            return user
87
        else:
1150 by William Grant
Refuse a +enrol if the user is already enrolled. This stops overwriting
88
            raise formencode.Invalid('User does not exist', value, state)
89
90
91
class NoEnrolmentValidator(formencode.FancyValidator):
92
    """A FormEncode validator that ensures absence of an enrolment.
93
94
    The state must have an 'offering' attribute.
95
    """
96
    def _to_python(self, value, state):
97
        if state.offering.get_enrolment(value):
98
            raise formencode.Invalid('User already enrolled', value, state)
99
        return value
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
100
101
1377 by Matt Giuca
database: Added finer-grained enrol permissions on offerings.
102
class RoleEnrolmentValidator(formencode.FancyValidator):
103
    """A FormEncode validator that checks permission to enrol users with a
104
    particular role.
105
106
    The state must have an 'offering' attribute.
107
    """
108
    def _to_python(self, value, state):
109
        if ("enrol_" + value) not in state.offering.get_permissions(state.user):
110
            raise formencode.Invalid('Not allowed to assign users that role',
111
                                     value, state)
112
        return value
113
114
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
115
class EnrolSchema(formencode.Schema):
1150 by William Grant
Refuse a +enrol if the user is already enrolled. This stops overwriting
116
    user = formencode.All(NoEnrolmentValidator(), UserValidator())
1377 by Matt Giuca
database: Added finer-grained enrol permissions on offerings.
117
    role = formencode.All(formencode.validators.OneOf(
118
                                ["lecturer", "tutor", "student"]),
119
                          RoleEnrolmentValidator(),
120
                          formencode.validators.UnicodeString())
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
121
122
1365 by Matt Giuca
Added a new view under Offering/+enrolments to display all staff and students in an offering.
123
class EnrolmentsView(XHTMLView):
124
    """A page which displays all users enrolled in an offering."""
125
    template = 'templates/enrolments.html'
126
    permission = 'edit'
127
128
    def populate(self, req, ctx):
129
        ctx['offering'] = self.context
130
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
131
class EnrolView(XHTMLView):
132
    """A form to enrol a user in an offering."""
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
133
    template = 'templates/enrol.html'
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
134
    tab = 'subjects'
1376 by Matt Giuca
database: More granular permissions on offerings: Added 'enrol' permission.
135
    permission = 'enrol'
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
136
137
    def filter(self, stream, ctx):
138
        return stream | HTMLFormFiller(data=ctx['data'])
139
140
    def populate(self, req, ctx):
141
        if req.method == 'POST':
142
            data = dict(req.get_fieldstorage())
143
            try:
144
                validator = EnrolSchema()
1150 by William Grant
Refuse a +enrol if the user is already enrolled. This stops overwriting
145
                req.offering = self.context # XXX: Getting into state.
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
146
                data = validator.to_python(data, state=req)
1377 by Matt Giuca
database: Added finer-grained enrol permissions on offerings.
147
                self.context.enrol(data['user'], data['role'])
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
148
                req.store.commit()
149
                req.throw_redirect(req.uri)
150
            except formencode.Invalid, e:
151
                errors = e.unpack_errors()
152
        else:
153
            data = {}
154
            errors = {}
155
156
        ctx['data'] = data or {}
157
        ctx['offering'] = self.context
1379 by Matt Giuca
Enrolments page: Don't show choices in the list if they are unauthorized. (Note that this is a UI tweak -- roles are already authz-checked.)
158
        ctx['roles_auth'] = self.context.get_permissions(req.user)
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
159
        ctx['errors'] = errors
160
1165.3.19 by William Grant
Rename SubjectProjectSetView to OfferingProjectsView.
161
class OfferingProjectsView(XHTMLView):
162
    """View the projects for an offering."""
163
    template = 'templates/offering_projects.html'
1165.2.3 by Nick Chadwick
Added a new Admin view, which allows for the administration of projects
164
    permission = 'edit'
1165.3.18 by William Grant
Put the project listing and view in the Subjects tab.
165
    tab = 'subjects'
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
166
1165.2.3 by Nick Chadwick
Added a new Admin view, which allows for the administration of projects
167
    def populate(self, req, ctx):
168
        self.plugin_styles[Plugin] = ["project.css"]
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
169
        self.plugin_scripts[Plugin] = ["project.js"]
1361 by William Grant
Remove the last +projectsets hardcoding.
170
        ctx['req'] = req
1165.2.3 by Nick Chadwick
Added a new Admin view, which allows for the administration of projects
171
        ctx['offering'] = self.context
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
172
        ctx['projectsets'] = []
1361 by William Grant
Remove the last +projectsets hardcoding.
173
        ctx['OfferingRESTView'] = OfferingRESTView
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
174
175
        #Open the projectset Fragment, and render it for inclusion
176
        #into the ProjectSets page
177
        #XXX: This could be a lot cleaner
178
        loader = genshi.template.TemplateLoader(".", auto_reload=True)
179
180
        set_fragment = os.path.join(os.path.dirname(__file__),
181
                "templates/projectset_fragment.html")
182
        project_fragment = os.path.join(os.path.dirname(__file__),
183
                "templates/project_fragment.html")
184
185
        for projectset in self.context.project_sets:
186
            settmpl = loader.load(set_fragment)
187
            setCtx = Context()
1358 by William Grant
Use the publishing framework to generate URLs to projectsets.
188
            setCtx['req'] = req
1165.3.30 by William Grant
Clean out the projectset fragment context.
189
            setCtx['projectset'] = projectset
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
190
            setCtx['projects'] = []
1358 by William Grant
Use the publishing framework to generate URLs to projectsets.
191
            setCtx['GroupsView'] = GroupsView
192
            setCtx['ProjectSetRESTView'] = ProjectSetRESTView
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
193
194
            for project in projectset.projects:
195
                projecttmpl = loader.load(project_fragment)
196
                projectCtx = Context()
1358 by William Grant
Use the publishing framework to generate URLs to projectsets.
197
                projectCtx['req'] = req
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
198
                projectCtx['project'] = project
199
200
                setCtx['projects'].append(
201
                        projecttmpl.generate(projectCtx))
202
203
            ctx['projectsets'].append(settmpl.generate(setCtx))
204
205
206
class ProjectView(XHTMLView):
1165.2.3 by Nick Chadwick
Added a new Admin view, which allows for the administration of projects
207
    """View the submissions for a ProjectSet"""
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
208
    template = "templates/project.html"
209
    permission = "edit"
1165.3.18 by William Grant
Put the project listing and view in the Subjects tab.
210
    tab = 'subjects'
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
211
1165.3.61 by William Grant
Provide a Subversion command to grab each submission.
212
    def build_subversion_url(self, svnroot, submission):
213
        princ = submission.assessed.principal
214
215
        if isinstance(princ, User):
216
            path = 'users/%s' % princ.login
217
        else:
218
            path = 'groups/%s_%s_%s_%s' % (
219
                    princ.project_set.offering.subject.short_name,
220
                    princ.project_set.offering.semester.year,
221
                    princ.project_set.offering.semester.semester,
222
                    princ.name
223
                    )
224
        return urlparse.urljoin(
225
                    svnroot,
226
                    os.path.join(path, submission.path[1:] if
227
                                       submission.path.startswith(os.sep) else
228
                                       submission.path))
229
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
230
    def populate(self, req, ctx):
1165.3.66 by William Grant
Prettify the submissions table.
231
        self.plugin_styles[Plugin] = ["project.css"]
232
1375.1.4 by William Grant
Indicate when there is nobody assigned to a project, and link to the page to fix that.
233
        ctx['req'] = req
234
        ctx['GroupsView'] = GroupsView
235
        ctx['EnrolView'] = EnrolView
1165.3.14 by William Grant
Improve ProjectView's template substantially.
236
        ctx['format_datetime_short'] = ivle.date.format_datetime_for_paragraph
1165.3.61 by William Grant
Provide a Subversion command to grab each submission.
237
        ctx['build_subversion_url'] = self.build_subversion_url
238
        ctx['svn_addr'] = req.config['urls']['svn_addr']
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
239
        ctx['project'] = self.context
1165.3.61 by William Grant
Provide a Subversion command to grab each submission.
240
        ctx['user'] = req.user
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
241
1099.1.115 by William Grant
Add tabs to the new framework. Move the app icons into the apps themselves.
242
class Plugin(ViewPlugin, MediaPlugin):
1294.2.70 by William Grant
Split out ivle.webapp.admin's routes into annotated functions in ivle.webapp.traversal.
243
    forward_routes = (root_to_subject, subject_to_offering,
244
                      offering_to_project, offering_to_projectset)
245
    reverse_routes = (subject_url, offering_url, projectset_url, project_url)
1294.2.52 by William Grant
Port subject-related views to object traversal.
246
247
    views = [(ApplicationRoot, ('subjects', '+index'), SubjectsView),
1365 by Matt Giuca
Added a new view under Offering/+enrolments to display all staff and students in an offering.
248
             (Offering, ('+enrolments', '+index'), EnrolmentsView),
1294.2.52 by William Grant
Port subject-related views to object traversal.
249
             (Offering, ('+enrolments', '+new'), EnrolView),
250
             (Offering, ('+projects', '+index'), OfferingProjectsView),
251
             (Project, '+index', ProjectView),
252
253
             (Offering, ('+projectsets', '+new'), OfferingRESTView, 'api'),
254
             (ProjectSet, ('+projects', '+new'), ProjectSetRESTView, 'api'),
255
             ]
1099.1.115 by William Grant
Add tabs to the new framework. Move the app icons into the apps themselves.
256
1294.2.94 by William Grant
Add a SubjectBreadcrumb.
257
    breadcrumbs = {Subject: SubjectBreadcrumb,
258
                   Offering: OfferingBreadcrumb,
1294.2.96 by William Grant
Add a UserBreadcrumb.
259
                   User: UserBreadcrumb,
1294.2.98 by William Grant
Add a ProjectBreadcrumb.
260
                   Project: ProjectBreadcrumb,
1294.2.89 by William Grant
Add an Offering breadcrumb.
261
                   }
262
1099.1.115 by William Grant
Add tabs to the new framework. Move the app icons into the apps themselves.
263
    tabs = [
1118 by matt.giuca
Rewrote tooltips for the four tabs visible by default.
264
        ('subjects', 'Subjects',
265
         'View subject content and complete worksheets',
266
         'subjects.png', 'subjects', 5)
1099.1.115 by William Grant
Add tabs to the new framework. Move the app icons into the apps themselves.
267
    ]
268
269
    media = 'subject-media'