24
23
import genshi.template
26
25
from ivle.webapp.media import media_url
27
from ivle.webapp.core import Plugin as CorePlugin
28
26
from ivle.webapp.base.views import BaseView
29
from ivle.webapp.base.plugins import ViewPlugin, OverlayPlugin
30
from ivle.webapp.errors import HTTPError, Unauthorized
27
from ivle.webapp.base.plugins import OverlayPlugin
32
31
class XHTMLView(BaseView):
39
38
template = 'template.html'
41
39
plugin_scripts = {}
46
41
overlay_blacklist = []
48
43
def __init__(self, req, **kwargs):
50
45
setattr(self, key, kwargs[key])
52
def filter(self, stream, ctx):
55
47
def render(self, req):
56
48
req.content_type = 'text/html' # TODO: Detect application/xhtml+xml
64
56
app_template = os.path.join(os.path.dirname(
65
57
inspect.getmodule(self).__file__), self.template)
58
req.write_html_head_foot = False
66
59
loader = genshi.template.TemplateLoader(".", auto_reload=True)
67
60
tmpl = loader.load(app_template)
68
app = self.filter(tmpl.generate(viewctx), viewctx)
61
app = tmpl.generate(viewctx)
71
63
for plugin in self.plugin_scripts:
72
64
for path in self.plugin_scripts[plugin]:
73
view_scripts.append(media_url(req, plugin, path))
65
req.scripts.append(media_url(req, plugin, path))
76
67
for plugin in self.plugin_styles:
77
68
for path in self.plugin_styles[plugin]:
78
view_styles.append(media_url(req, plugin, path))
69
req.styles.append(media_url(req, plugin, path))
81
72
ctx = genshi.template.Context()
83
overlay_bits = self.render_overlays(req) if req.user else [[]]*4
84
ctx['overlays'] = overlay_bits[0]
86
ctx['styles'] = [media_url(req, CorePlugin, 'ivle.css')]
87
ctx['styles'] += view_styles
88
ctx['styles'] += overlay_bits[1]
90
ctx['scripts'] = [media_url(req, CorePlugin, path) for path in
91
('util.js', 'json2.js', 'md5.js')]
92
ctx['scripts'].append(media_url(req, '+external/jquery', 'jquery.js'))
93
ctx['scripts'] += view_scripts
94
ctx['scripts'] += overlay_bits[2]
96
ctx['scripts_init'] = self.scripts_init + overlay_bits[3]
73
# XXX: Leave this here!! (Before req.styles is read)
74
ctx['overlays'] = self.render_overlays(req)
75
ctx['app_styles'] = req.styles
76
ctx['scripts'] = req.scripts
77
ctx['scripts_init'] = req.scripts_init
97
78
ctx['app_template'] = app
98
ctx['title_img'] = media_url(req, CorePlugin,
99
"images/chrome/title.png")
100
79
self.populate_headings(req, ctx)
101
80
tmpl = loader.load(os.path.join(os.path.dirname(__file__),
102
81
'ivle-headings.html'))
108
87
def populate_headings(self, req, ctx):
109
88
ctx['favicon'] = None
110
ctx['root_dir'] = req.config['urls']['root']
111
ctx['public_host'] = req.config['urls']['public_host']
112
ctx['svn_base'] = req.config['urls']['svn_addr']
89
ctx['root_dir'] = ivle.conf.root_dir
90
ctx['public_host'] = ivle.conf.public_host
113
91
ctx['write_javascript_settings'] = req.write_javascript_settings
115
93
ctx['login'] = req.user.login
119
97
ctx['login'] = None
120
98
ctx['logged_in'] = False
121
99
ctx['publicmode'] = req.publicmode
122
if hasattr(self, 'help'):
123
ctx['help_path'] = self.help
125
100
ctx['apps_in_tabs'] = []
126
for plugin in req.config.plugin_index[ViewPlugin]:
127
if not hasattr(plugin, 'tabs'):
130
for tab in plugin.tabs:
131
# tab is a tuple: name, title, desc, icon, path
133
new_app['this_app'] = hasattr(self, 'tab') \
134
and tab[0] == self.tab
137
if tab[3] is not None:
138
new_app['has_icon'] = True
139
icon_url = media_url(req, plugin, tab[3])
140
new_app['icon_url'] = icon_url
141
if new_app['this_app']:
142
ctx['favicon'] = icon_url
144
new_app['has_icon'] = False
145
new_app['path'] = req.make_path(tab[4])
146
new_app['desc'] = tab[2]
147
new_app['name'] = tab[1]
148
new_app['weight'] = tab[5]
149
ctx['apps_in_tabs'].append(new_app)
151
ctx['apps_in_tabs'].sort(key=lambda tab: tab['weight'])
101
for urlname in ivle.conf.apps.apps_in_tabs:
103
app = ivle.conf.apps.app_url[urlname]
104
new_app['this_app'] = hasattr(self, 'appname') \
105
and urlname == self.appname
107
new_app['has_icon'] = True
108
icon_dir = ivle.conf.apps.app_icon_dir
109
icon_url = ivle.util.make_path(os.path.join(icon_dir, app.icon))
110
new_app['icon_url'] = icon_url
111
if new_app['this_app']:
112
ctx['favicon'] = icon_url
114
new_app['has_icon'] = False
115
new_app['path'] = ivle.util.make_path(urlname)
116
new_app['desc'] = app.desc
117
new_app['name'] = app.name
118
ctx['apps_in_tabs'].append(new_app)
153
120
def render_overlays(self, req):
154
121
"""Generate XML streams for the overlays.
163
if not self.allow_overlays:
164
return (overlays, styles, scripts, scripts_init)
166
for plugin in req.config.plugin_index[OverlayPlugin]:
127
for plugin in req.plugin_index[OverlayPlugin]:
167
128
for overclass in plugin.overlays:
168
129
if overclass in self.overlay_blacklist:
171
132
#TODO: Re-factor this to look nicer
172
133
for mplugin in overlay.plugin_scripts:
173
134
for path in overlay.plugin_scripts[mplugin]:
174
scripts.append(media_url(req, mplugin, path))
135
req.scripts.append(media_url(req, mplugin, path))
176
137
for mplugin in overlay.plugin_styles:
177
138
for path in overlay.plugin_styles[mplugin]:
178
styles.append(media_url(req, mplugin, path))
139
req.styles.append(media_url(req, mplugin, path))
180
scripts_init += overlay.plugin_scripts_init
141
req.scripts_init += overlay.plugin_scripts_init
182
143
overlays.append(overlay.render(req))
183
return (overlays, styles, scripts, scripts_init)
186
def get_error_view(cls, e):
187
view_map = {HTTPError: XHTMLErrorView,
188
Unauthorized: XHTMLUnauthorizedView}
189
for exccls in inspect.getmro(type(e)):
190
if exccls in view_map:
191
return view_map[exccls]
193
146
class XHTMLErrorView(XHTMLView):
194
147
template = 'xhtmlerror.html'
199
152
def populate(self, req, ctx):
200
153
ctx['exception'] = self.context
202
class XHTMLUnauthorizedView(XHTMLErrorView):
203
template = 'xhtmlunauthorized.html'
205
def __init__(self, req, exception):
206
super(XHTMLUnauthorizedView, self).__init__(req, exception)
209
# Not logged in. Redirect to login page.
213
query_string = '?url=' + urllib.quote(req.uri, safe="/~")
214
req.throw_redirect('/+login' + query_string)