28
28
from ivle.webapp.base.views import BaseView
29
29
from ivle.webapp.base.plugins import ViewPlugin, OverlayPlugin
30
30
from ivle.webapp.errors import HTTPError, Unauthorized
31
from ivle.webapp.publisher import NoPath
32
from ivle.webapp.breadcrumbs import Breadcrumber
32
34
class XHTMLView(BaseView):
39
41
template = 'template.html'
45
42
allow_overlays = True
46
overlay_blacklist = []
48
def __init__(self, req, **kwargs):
50
setattr(self, key, kwargs[key])
43
breadcrumb_text = None
46
def __init__(self, *args, **kwargs):
47
super(XHTMLView, self).__init__(*args, **kwargs)
49
# We use a single loader for all views, so we can cache the
50
# parsed templates. auto_reload is convenient and has a minimal
51
# performance penalty, so we'll leave it on.
52
if self.__class__._loader is None:
53
self.__class__._loader = genshi.template.TemplateLoader(
54
".", auto_reload=True,
57
self.overlay_blacklist = []
59
self.plugin_scripts = {}
60
self.plugin_styles = {}
61
self.scripts_init = []
63
self.extra_breadcrumbs = []
64
self.overlay_blacklist = []
66
def get_context_ancestry(self, req):
67
return req.publisher.get_ancestors(self.context)
52
69
def filter(self, stream, ctx):
64
81
app_template = os.path.join(os.path.dirname(
65
82
inspect.getmodule(self).__file__), self.template)
66
loader = genshi.template.TemplateLoader(".", auto_reload=True)
67
tmpl = loader.load(app_template)
83
tmpl = self._loader.load(app_template)
68
84
app = self.filter(tmpl.generate(viewctx), viewctx)
96
112
ctx['scripts_init'] = self.scripts_init + overlay_bits[3]
97
113
ctx['app_template'] = app
98
114
ctx['title_img'] = media_url(req, CorePlugin,
99
"images/chrome/title.png")
115
"images/chrome/root-breadcrumb.png")
117
ancestry = self.get_context_ancestry(req)
121
crumber = Breadcrumber(req)
123
ctx['breadcrumbs'] = []
124
if not req.publicmode:
125
for ancestor in ancestry:
126
crumb = crumber.crumb(ancestor)
130
if hasattr(crumb, 'extra_breadcrumbs_before'):
131
ctx['breadcrumbs'].extend(crumb.extra_breadcrumbs_before)
132
ctx['breadcrumbs'].append(crumb)
133
if hasattr(crumb, 'extra_breadcrumbs_after'):
134
ctx['breadcrumbs'].extend(crumb.extra_breadcrumbs_after)
136
# If the view has specified text for a breadcrumb, add one.
137
if self.breadcrumb_text:
138
ctx['breadcrumbs'].append(ViewBreadcrumb(req, self))
140
# Allow the view to add its own fake breadcrumbs.
141
ctx['breadcrumbs'].extend(self.extra_breadcrumbs)
100
143
self.populate_headings(req, ctx)
101
tmpl = loader.load(os.path.join(os.path.dirname(__file__),
144
tmpl = self._loader.load(os.path.join(os.path.dirname(__file__),
102
145
'ivle-headings.html'))
103
146
req.write(tmpl.generate(ctx).render('xhtml', doctype='xhtml'))
130
173
for tab in plugin.tabs:
131
# tab is a tuple: name, title, desc, icon, path
174
# tab is a tuple: name, title, desc, icon, path, weight, admin
175
# (Admin is optional, defaults to false)
133
177
new_app['this_app'] = hasattr(self, 'tab') \
134
178
and tab[0] == self.tab
142
186
ctx['favicon'] = icon_url
144
188
new_app['has_icon'] = False
189
# The following check is here, so it is AFTER setting the
190
# icon, but BEFORE actually installing the tab in the menu
191
if len(tab) > 6 and tab[6]:
193
if not (req.user and req.user.admin):
145
195
new_app['path'] = req.make_path(tab[4])
146
196
new_app['desc'] = tab[2]
147
197
new_app['name'] = tab[1]
193
243
class XHTMLErrorView(XHTMLView):
194
244
template = 'xhtmlerror.html'
196
def __init__(self, req, exception):
197
self.context = exception
246
def __init__(self, req, context, lastobj):
247
super(XHTMLErrorView, self).__init__(req, context)
248
self.lastobj = lastobj
250
def get_context_ancestry(self, req):
251
return req.publisher.get_ancestors(self.lastobj)
199
253
def populate(self, req, ctx):
200
255
ctx['exception'] = self.context
256
req.headers_out['X-IVLE-Error'] = self.context.message
202
258
class XHTMLUnauthorizedView(XHTMLErrorView):
203
259
template = 'xhtmlunauthorized.html'
205
def __init__(self, req, exception):
206
super(XHTMLUnauthorizedView, self).__init__(req, exception)
261
def __init__(self, req, exception, lastobj):
262
super(XHTMLUnauthorizedView, self).__init__(req, exception, lastobj)
264
if not req.publicmode and req.user is None:
209
265
# Not logged in. Redirect to login page.
210
266
if req.uri == '/':
211
267
query_string = ''
214
270
req.throw_redirect('/+login' + query_string)
274
class ViewBreadcrumb(object):
275
def __init__(self, req, context):
277
self.context = context
281
return self.context.breadcrumb_text