~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
26
import urllib
27
import cgi
28
1125 by William Grant
Rework ivle.webapp.admin.subjects#SubjectsView to split offerings nicely by
29
from storm.locals import Desc
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
30
import genshi
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
31
from genshi.filters import HTMLFormFiller
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
32
from genshi.template import Context, TemplateLoader
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
33
import formencode
1125 by William Grant
Rework ivle.webapp.admin.subjects#SubjectsView to split offerings nicely by
34
1099.1.34 by William Grant
Split up ivle.webapp.base.views into ivle.webapp.base.{rest,xhtml}, as it was
35
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.
36
from ivle.webapp.base.plugins import ViewPlugin, MediaPlugin
1099.1.20 by William Grant
ivle.webapp.admin.subject: Port www/apps/subjects to new framework.
37
from ivle.webapp.errors import NotFound
1165.3.9 by Nick Chadwick
merge from trunk
38
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
39
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
40
                          ProjectSet, Project, ProjectSubmission
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
41
from ivle import util
1165.3.14 by William Grant
Improve ProjectView's template substantially.
42
import ivle.date
621 by mattgiuca
Added 2 new apps: home and subjects. Both fairly incomplete, just a basic
43
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
44
from ivle.webapp.admin.projectservice import ProjectSetRESTView,\
45
                                             ProjectRESTView
46
from ivle.webapp.admin.offeringservice import OfferingRESTView
47
1099.1.20 by William Grant
ivle.webapp.admin.subject: Port www/apps/subjects to new framework.
48
49
class SubjectsView(XHTMLView):
50
    '''The view of the list of subjects.'''
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
51
    template = 'templates/subjects.html'
1116 by William Grant
Move the old tutorial views into the 'subjects' tab, so they get the right
52
    tab = 'subjects'
1099.1.20 by William Grant
ivle.webapp.admin.subject: Port www/apps/subjects to new framework.
53
1099.1.110 by William Grant
Implement an authorization system in the new framework. This breaks the REST
54
    def authorize(self, req):
1138 by William Grant
SubjectsView now tells users if they have no enrolments.
55
        return req.user is not None
1099.1.110 by William Grant
Implement an authorization system in the new framework. This breaks the REST
56
1099.1.20 by William Grant
ivle.webapp.admin.subject: Port www/apps/subjects to new framework.
57
    def populate(self, req, ctx):
1139 by William Grant
Show group administration links on SubjectsView where privileges allow it.
58
        ctx['user'] = req.user
1125 by William Grant
Rework ivle.webapp.admin.subjects#SubjectsView to split offerings nicely by
59
        ctx['semesters'] = []
60
        for semester in req.store.find(Semester).order_by(Desc(Semester.year),
61
                                                     Desc(Semester.semester)):
62
            enrolments = semester.enrolments.find(user=req.user)
63
            if enrolments.count():
64
                ctx['semesters'].append((semester, enrolments))
1099.1.20 by William Grant
ivle.webapp.admin.subject: Port www/apps/subjects to new framework.
65
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
66
67
class UserValidator(formencode.FancyValidator):
68
    """A FormEncode validator that turns a username into a user.
69
70
    The state must have a 'store' attribute, which is the Storm store
71
    to use."""
72
    def _to_python(self, value, state):
73
        user = User.get_by_login(state.store, value)
74
        if user:
75
            return user
76
        else:
1150 by William Grant
Refuse a +enrol if the user is already enrolled. This stops overwriting
77
            raise formencode.Invalid('User does not exist', value, state)
78
79
80
class NoEnrolmentValidator(formencode.FancyValidator):
81
    """A FormEncode validator that ensures absence of an enrolment.
82
83
    The state must have an 'offering' attribute.
84
    """
85
    def _to_python(self, value, state):
86
        if state.offering.get_enrolment(value):
87
            raise formencode.Invalid('User already enrolled', value, state)
88
        return value
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
89
90
91
class EnrolSchema(formencode.Schema):
1150 by William Grant
Refuse a +enrol if the user is already enrolled. This stops overwriting
92
    user = formencode.All(NoEnrolmentValidator(), UserValidator())
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
93
94
95
class EnrolView(XHTMLView):
96
    """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
97
    template = 'templates/enrol.html'
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
98
    tab = 'subjects'
99
    permission = 'edit'
100
101
    def __init__(self, req, subject, year, semester):
102
        """Find the given offering by subject, year and semester."""
103
        self.context = req.store.find(Offering,
104
            Offering.subject_id == Subject.id,
105
            Subject.short_name == subject,
106
            Offering.semester_id == Semester.id,
107
            Semester.year == year,
108
            Semester.semester == semester).one()
109
110
        if not self.context:
111
            raise NotFound()
112
113
    def filter(self, stream, ctx):
114
        return stream | HTMLFormFiller(data=ctx['data'])
115
116
    def populate(self, req, ctx):
117
        if req.method == 'POST':
118
            data = dict(req.get_fieldstorage())
119
            try:
120
                validator = EnrolSchema()
1150 by William Grant
Refuse a +enrol if the user is already enrolled. This stops overwriting
121
                req.offering = self.context # XXX: Getting into state.
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
122
                data = validator.to_python(data, state=req)
123
                self.context.enrol(data['user'])
124
                req.store.commit()
125
                req.throw_redirect(req.uri)
126
            except formencode.Invalid, e:
127
                errors = e.unpack_errors()
128
        else:
129
            data = {}
130
            errors = {}
131
132
        ctx['data'] = data or {}
133
        ctx['offering'] = self.context
134
        ctx['errors'] = errors
135
1165.3.19 by William Grant
Rename SubjectProjectSetView to OfferingProjectsView.
136
class OfferingProjectsView(XHTMLView):
137
    """View the projects for an offering."""
138
    template = 'templates/offering_projects.html'
1165.2.3 by Nick Chadwick
Added a new Admin view, which allows for the administration of projects
139
    permission = 'edit'
1165.3.18 by William Grant
Put the project listing and view in the Subjects tab.
140
    tab = 'subjects'
1165.2.3 by Nick Chadwick
Added a new Admin view, which allows for the administration of projects
141
    
142
    def __init__(self, req, subject, year, semester):
143
        self.context = req.store.find(Offering,
144
            Offering.subject_id == Subject.id,
145
            Subject.short_name == subject,
146
            Offering.semester_id == Semester.id,
147
            Semester.year == year,
148
            Semester.semester == semester).one()
149
150
        if not self.context:
151
            raise NotFound()
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
152
153
    def project_url(self, projectset, project):
1165.3.15 by William Grant
Remove the ProjectSet from Project URLs.
154
        return "/subjects/%s/%s/%s/+projects/%s" % (
155
                    self.context.subject.short_name,
156
                    self.context.semester.year,
157
                    self.context.semester.semester,
158
                    project.short_name
159
                    )
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
160
161
    def new_project_url(self, projectset):
162
        return "/api/subjects/" + self.context.subject.short_name + "/" +\
163
                self.context.semester.year + "/" + \
164
                self.context.semester.semester + "/+projectsets/" +\
165
                str(projectset.id) + "/+projects/+new"
1165.2.3 by Nick Chadwick
Added a new Admin view, which allows for the administration of projects
166
    
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"]
1165.2.3 by Nick Chadwick
Added a new Admin view, which allows for the administration of projects
170
        ctx['offering'] = self.context
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
171
        ctx['projectsets'] = []
172
173
        #Open the projectset Fragment, and render it for inclusion
174
        #into the ProjectSets page
175
        #XXX: This could be a lot cleaner
176
        loader = genshi.template.TemplateLoader(".", auto_reload=True)
177
178
        set_fragment = os.path.join(os.path.dirname(__file__),
179
                "templates/projectset_fragment.html")
180
        project_fragment = os.path.join(os.path.dirname(__file__),
181
                "templates/project_fragment.html")
182
183
        for projectset in self.context.project_sets:
184
            settmpl = loader.load(set_fragment)
185
            setCtx = Context()
1165.3.30 by William Grant
Clean out the projectset fragment context.
186
            setCtx['projectset'] = projectset
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
187
            setCtx['new_project_url'] = self.new_project_url(projectset)
188
            setCtx['projects'] = []
189
190
            for project in projectset.projects:
191
                projecttmpl = loader.load(project_fragment)
192
                projectCtx = Context()
193
                projectCtx['project'] = project
194
                projectCtx['project_url'] = self.project_url(projectset, project)
195
196
                setCtx['projects'].append(
197
                        projecttmpl.generate(projectCtx))
198
199
            ctx['projectsets'].append(settmpl.generate(setCtx))
200
201
202
class ProjectView(XHTMLView):
1165.2.3 by Nick Chadwick
Added a new Admin view, which allows for the administration of projects
203
    """View the submissions for a ProjectSet"""
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
204
    template = "templates/project.html"
205
    permission = "edit"
1165.3.18 by William Grant
Put the project listing and view in the Subjects tab.
206
    tab = 'subjects'
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
207
1165.3.15 by William Grant
Remove the ProjectSet from Project URLs.
208
    def __init__(self, req, subject, year, semester, project):
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
209
        self.context = req.store.find(Project,
210
                Project.short_name == project,
211
                Project.project_set_id == ProjectSet.id,
212
                ProjectSet.offering_id == Offering.id,
213
                Offering.semester_id == Semester.id,
214
                Semester.year == year,
215
                Semester.semester == semester,
216
                Offering.subject_id == Subject.id,
217
                Subject.short_name == subject).one()
218
        if self.context is None:
219
            raise NotFound()
220
221
    def populate(self, req, ctx):
1165.3.14 by William Grant
Improve ProjectView's template substantially.
222
        ctx['format_datetime_short'] = ivle.date.format_datetime_for_paragraph
223
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
224
        ctx['project'] = self.context
225
        ctx['assesseds'] = self.context.assesseds
226
1165.3.8 by Nick Chadwick
Added a total submissions and total assesseds to the project view
227
        ctx['submissions'] = []
228
        for assessed in self.context.assesseds:
229
            if assessed.submissions.count() > 0:
230
                ctx['submissions'].append(
1165.3.13 by William Grant
Fix ProjectView's latest submission calculation. It returned a ResultSet.
231
                        assessed.submissions.order_by(ProjectSubmission.date_submitted)[-1])
1165.3.8 by Nick Chadwick
Added a total submissions and total assesseds to the project view
232
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
233
1099.1.115 by William Grant
Add tabs to the new framework. Move the app icons into the apps themselves.
234
class Plugin(ViewPlugin, MediaPlugin):
1099.1.20 by William Grant
ivle.webapp.admin.subject: Port www/apps/subjects to new framework.
235
    urls = [
236
        ('subjects/', SubjectsView),
1149 by William Grant
Allow tutors and lecturers to enrol people in their offerings.
237
        ('subjects/:subject/:year/:semester/+enrolments/+new', EnrolView),
1165.3.19 by William Grant
Rename SubjectProjectSetView to OfferingProjectsView.
238
        ('subjects/:subject/:year/:semester/+projects', OfferingProjectsView),
1165.3.15 by William Grant
Remove the ProjectSet from Project URLs.
239
        ('subjects/:subject/:year/:semester/+projects/:project', ProjectView),
1165.2.3 by Nick Chadwick
Added a new Admin view, which allows for the administration of projects
240
        #API Views
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
241
        ('api/subjects/:subject/:year/:semester/+projectsets/+new',
242
            OfferingRESTView),
243
        ('api/subjects/:subject/:year/:semester/+projectsets/:projectset/+projects/+new',
244
            ProjectSetRESTView),
1165.3.15 by William Grant
Remove the ProjectSet from Project URLs.
245
        ('api/subjects/:subject/:year/:semester/+projects/:project', 
1165.3.2 by Nick Chadwick
Created a new view for IVLE, allowing lecturers and tutors to
246
            ProjectRESTView),
247
1099.1.20 by William Grant
ivle.webapp.admin.subject: Port www/apps/subjects to new framework.
248
    ]
1099.1.115 by William Grant
Add tabs to the new framework. Move the app icons into the apps themselves.
249
250
    tabs = [
1118 by matt.giuca
Rewrote tooltips for the four tabs visible by default.
251
        ('subjects', 'Subjects',
252
         'View subject content and complete worksheets',
253
         'subjects.png', 'subjects', 5)
1099.1.115 by William Grant
Add tabs to the new framework. Move the app icons into the apps themselves.
254
    ]
255
256
    media = 'subject-media'