23
24
import genshi.template
25
26
from ivle.webapp.media import media_url
27
from ivle.webapp.core import Plugin as CorePlugin
26
28
from ivle.webapp.base.views import BaseView
27
from ivle.webapp.base.plugins import OverlayPlugin
29
from ivle.webapp.base.plugins import ViewPlugin, OverlayPlugin
28
30
from ivle.webapp.errors import HTTPError, Unauthorized
32
32
class XHTMLView(BaseView):
39
39
template = 'template.html'
40
41
plugin_scripts = {}
42
46
overlay_blacklist = []
44
48
def __init__(self, req, **kwargs):
46
50
setattr(self, key, kwargs[key])
52
def filter(self, stream, ctx):
48
55
def render(self, req):
49
56
req.content_type = 'text/html' # TODO: Detect application/xhtml+xml
57
64
app_template = os.path.join(os.path.dirname(
58
65
inspect.getmodule(self).__file__), self.template)
59
req.write_html_head_foot = False
60
66
loader = genshi.template.TemplateLoader(".", auto_reload=True)
61
67
tmpl = loader.load(app_template)
62
app = tmpl.generate(viewctx)
68
app = self.filter(tmpl.generate(viewctx), viewctx)
64
71
for plugin in self.plugin_scripts:
65
72
for path in self.plugin_scripts[plugin]:
66
req.scripts.append(media_url(req, plugin, path))
73
view_scripts.append(media_url(req, plugin, path))
68
76
for plugin in self.plugin_styles:
69
77
for path in self.plugin_styles[plugin]:
70
req.styles.append(media_url(req, plugin, path))
78
view_styles.append(media_url(req, plugin, path))
73
81
ctx = genshi.template.Context()
74
# XXX: Leave this here!! (Before req.styles is read)
75
ctx['overlays'] = self.render_overlays(req)
76
ctx['app_styles'] = req.styles
77
ctx['scripts'] = req.scripts
78
ctx['scripts_init'] = req.scripts_init
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]
79
97
ctx['app_template'] = app
98
ctx['title_img'] = media_url(req, CorePlugin,
99
"images/chrome/title.png")
80
100
self.populate_headings(req, ctx)
81
101
tmpl = loader.load(os.path.join(os.path.dirname(__file__),
82
102
'ivle-headings.html'))
88
108
def populate_headings(self, req, ctx):
89
109
ctx['favicon'] = None
90
ctx['root_dir'] = ivle.conf.root_dir
91
ctx['public_host'] = ivle.conf.public_host
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']
92
113
ctx['write_javascript_settings'] = req.write_javascript_settings
94
115
ctx['login'] = req.user.login
98
119
ctx['login'] = None
99
120
ctx['logged_in'] = False
100
121
ctx['publicmode'] = req.publicmode
101
ctx['apps_in_tabs'] = []
102
122
if hasattr(self, 'help'):
103
123
ctx['help_path'] = self.help
104
for urlname in ivle.conf.apps.apps_in_tabs:
106
app = ivle.conf.apps.app_url[urlname]
107
new_app['this_app'] = hasattr(self, 'appname') \
108
and urlname == self.appname
110
new_app['has_icon'] = True
111
icon_dir = ivle.conf.apps.app_icon_dir
112
icon_url = ivle.util.make_path(os.path.join(icon_dir, app.icon))
113
new_app['icon_url'] = icon_url
114
if new_app['this_app']:
115
ctx['favicon'] = icon_url
117
new_app['has_icon'] = False
118
new_app['path'] = ivle.util.make_path(urlname)
119
new_app['desc'] = app.desc
120
new_app['name'] = app.name
121
ctx['apps_in_tabs'].append(new_app)
125
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'])
123
153
def render_overlays(self, req):
124
154
"""Generate XML streams for the overlays.
130
for plugin in req.plugin_index[OverlayPlugin]:
163
if not self.allow_overlays:
164
return (overlays, styles, scripts, scripts_init)
166
for plugin in req.config.plugin_index[OverlayPlugin]:
131
167
for overclass in plugin.overlays:
132
168
if overclass in self.overlay_blacklist:
135
171
#TODO: Re-factor this to look nicer
136
172
for mplugin in overlay.plugin_scripts:
137
173
for path in overlay.plugin_scripts[mplugin]:
138
req.scripts.append(media_url(req, mplugin, path))
174
scripts.append(media_url(req, mplugin, path))
140
176
for mplugin in overlay.plugin_styles:
141
177
for path in overlay.plugin_styles[mplugin]:
142
req.styles.append(media_url(req, mplugin, path))
178
styles.append(media_url(req, mplugin, path))
144
req.scripts_init += overlay.plugin_scripts_init
180
scripts_init += overlay.plugin_scripts_init
146
182
overlays.append(overlay.render(req))
183
return (overlays, styles, scripts, scripts_init)
150
186
def get_error_view(cls, e):
169
205
def __init__(self, req, exception):
170
206
super(XHTMLUnauthorizedView, self).__init__(req, exception)
171
208
if req.user is None:
172
209
# Not logged in. Redirect to login page.
173
req.throw_redirect('/') # XXX: Need proper URL.
213
query_string = '?url=' + urllib.quote(req.uri, safe="/~")
214
req.throw_redirect('/+login' + query_string)