1 | # -*- coding: utf-8 -*- |
---|
2 | import grok |
---|
3 | import zope.interface |
---|
4 | from zope.component import getMultiAdapter |
---|
5 | from zope.location.interfaces import ISite |
---|
6 | from waeup.interfaces import (IUniversity, IWAeUPObject, IWAeUPXMLExporter, |
---|
7 | IWAeUPXMLImporter) |
---|
8 | |
---|
9 | grok.context(zope.interface.Interface) |
---|
10 | |
---|
11 | class Index(grok.View): |
---|
12 | """main structure for all pages""" |
---|
13 | grok.template('master') |
---|
14 | |
---|
15 | class Manage(grok.View): |
---|
16 | """Admin view for waeup objects. |
---|
17 | """ |
---|
18 | grok.context(IWAeUPObject) |
---|
19 | grok.template('master') |
---|
20 | |
---|
21 | class Add(grok.View): |
---|
22 | """Admin add form wrapper for waeup objects. |
---|
23 | """ |
---|
24 | grok.context(IWAeUPObject) |
---|
25 | grok.template('master') |
---|
26 | |
---|
27 | class ExportXML(grok.View): |
---|
28 | """Deliver an XML representation of the context. |
---|
29 | """ |
---|
30 | grok.name('export.xml') |
---|
31 | grok.require('waeup.manageUniversity') |
---|
32 | |
---|
33 | def render(self): |
---|
34 | exporter = IWAeUPXMLExporter(self.context) |
---|
35 | xml = exporter.export().read() |
---|
36 | self.response.setHeader( |
---|
37 | 'Content-Type', 'text/xml; charset=UTF-8') |
---|
38 | return xml |
---|
39 | |
---|
40 | class ImportXML(grok.View): |
---|
41 | """Replace the context object by an object created from an XML |
---|
42 | representation. |
---|
43 | |
---|
44 | XXX: This does not work for ISite objects, i.e. for instance |
---|
45 | for complete University objects. |
---|
46 | """ |
---|
47 | grok.require('waeup.manageUniversity') |
---|
48 | grok.template('master') |
---|
49 | |
---|
50 | def update(self, xmlfile=None, CANCEL=None, SUBMIT=None): |
---|
51 | if CANCEL is not None: |
---|
52 | self.redirect(self.url(self.context)) |
---|
53 | return |
---|
54 | if not xmlfile: |
---|
55 | return |
---|
56 | importer = IWAeUPXMLImporter(self.context) |
---|
57 | obj = importer.doImport(xmlfile) |
---|
58 | if type(obj) != type(self.context): |
---|
59 | return |
---|
60 | parent = self.context.__parent__ |
---|
61 | name = self.context.__name__ |
---|
62 | self.context = obj |
---|
63 | if hasattr(parent, name): |
---|
64 | setattr(parent, name, obj) |
---|
65 | else: |
---|
66 | del parent[name] |
---|
67 | parent[name] = obj |
---|
68 | pass |
---|
69 | return |
---|
70 | |
---|
71 | |
---|
72 | |
---|
73 | class Head(grok.ViewletManager): |
---|
74 | """additions to HTML head""" |
---|
75 | grok.name('head') |
---|
76 | |
---|
77 | class Title(grok.Viewlet): |
---|
78 | grok.viewletmanager(Head) |
---|
79 | |
---|
80 | class AppCSS(grok.Viewlet): |
---|
81 | grok.viewletmanager(Head) |
---|
82 | |
---|
83 | class Header(grok.ViewletManager): |
---|
84 | grok.name('header') |
---|
85 | |
---|
86 | class Logo(grok.Viewlet): |
---|
87 | grok.viewletmanager(Header) |
---|
88 | grok.order(1) |
---|
89 | |
---|
90 | def getAppTitle(self): |
---|
91 | """Get the `name` attribute of the local site object. |
---|
92 | |
---|
93 | This is normally the waeup application or IUniversity object. |
---|
94 | If this object has no ``name`` attribute, then we return the |
---|
95 | empty string. |
---|
96 | """ |
---|
97 | app = grok.getSite() |
---|
98 | return getattr(app, 'name', u'') |
---|
99 | |
---|
100 | class NavigationBar(grok.Viewlet): |
---|
101 | grok.viewletmanager(Header) |
---|
102 | grok.order(2) |
---|
103 | |
---|
104 | def getSite(self): |
---|
105 | return grok.getSite() |
---|
106 | |
---|
107 | class LeftSidebar(grok.ViewletManager): |
---|
108 | grok.name('left') |
---|
109 | |
---|
110 | class AuthUser(grok.Viewlet): |
---|
111 | grok.viewletmanager(LeftSidebar) |
---|
112 | grok.order(1) |
---|
113 | |
---|
114 | class Login(grok.Viewlet): |
---|
115 | """This viewlet allows to login in the sidebar. |
---|
116 | """ |
---|
117 | grok.viewletmanager(LeftSidebar) |
---|
118 | grok.context(IUniversity) |
---|
119 | grok.view(Index) |
---|
120 | grok.order(2) |
---|
121 | |
---|
122 | def isAuthenticated(self): |
---|
123 | """Is the calling user authenticated? |
---|
124 | """ |
---|
125 | return self.request.principal.id != 'zope.anybody' |
---|
126 | |
---|
127 | class ExportLink(grok.Viewlet): |
---|
128 | grok.viewletmanager(LeftSidebar) |
---|
129 | grok.view(Index) |
---|
130 | grok.order(99) |
---|
131 | grok.require('waeup.manageUniversity') |
---|
132 | |
---|
133 | def render(self): |
---|
134 | return '<div class="portlet"><a href="export.xml">%s</a></div>' % ( |
---|
135 | 'Export as XML',) |
---|
136 | |
---|
137 | class ImportLink(grok.Viewlet): |
---|
138 | grok.viewletmanager(LeftSidebar) |
---|
139 | grok.view(Index) |
---|
140 | grok.order(99) |
---|
141 | grok.require('waeup.manageUniversity') |
---|
142 | |
---|
143 | def render(self): |
---|
144 | if ISite.providedBy(self.context): |
---|
145 | # We cannot simply replace local sites. |
---|
146 | return '' |
---|
147 | return '<div class="portlet"><a href="importxml">%s</a></div>' % ( |
---|
148 | 'Import from XML',) |
---|
149 | |
---|
150 | class MainArea(grok.ViewletManager): |
---|
151 | grok.name('main') |
---|
152 | |
---|
153 | class ImportXMLViewlet(grok.Viewlet): |
---|
154 | grok.viewletmanager(MainArea) |
---|
155 | grok.view(ImportXML) |
---|
156 | |
---|
157 | |
---|
158 | class Footer(grok.ViewletManager): |
---|
159 | grok.name('footer') |
---|
160 | |
---|
161 | class Copyright(grok.Viewlet): |
---|
162 | grok.viewletmanager(Footer) |
---|
163 | |
---|
164 | class FormWrapMixin(object): |
---|
165 | """Mixin for viewlets that renders forms. |
---|
166 | |
---|
167 | XXX: Need tests for this. |
---|
168 | |
---|
169 | This is a mixin that provides some convenience features for |
---|
170 | viewlets that want to render forms, by overriding the default |
---|
171 | `render()` and `update()` methods. |
---|
172 | |
---|
173 | To create a viewlet that renders a form, you can define one as |
---|
174 | usual but also derive from this mixin-class. |
---|
175 | |
---|
176 | Say we have a usual form view like this:: |
---|
177 | |
---|
178 | >>> import grok |
---|
179 | >>> class EditForm(grok.EditForm): |
---|
180 | ... grok.context(SomeType) |
---|
181 | ... grok.name('addsometype') |
---|
182 | ... form_fields = grok.AutoFields(IUniversity) |
---|
183 | ... @grok.action('Save') |
---|
184 | ... def save(self, **data): |
---|
185 | ... self.applyData(self.context, **data) |
---|
186 | ... return |
---|
187 | |
---|
188 | then we can create a viewlet that displays this view like this:: |
---|
189 | |
---|
190 | >>> import grok |
---|
191 | >>> from waeup.viewlets import FormWrapMixin |
---|
192 | >>> class EditFormViewlet(FormWrapMixin, grok.Viewlet): |
---|
193 | ... grok.viewletmanager(MainArea) |
---|
194 | ... grok.context(ISomeType) |
---|
195 | ... grok.view(Manage) |
---|
196 | ... formview_name = 'addsometype' |
---|
197 | |
---|
198 | Here we define a regular viewlet with two modifications: |
---|
199 | |
---|
200 | * it is also derived from `FormWrapMixin` and |
---|
201 | |
---|
202 | * it provides an attribute ``formview_name`` which tells us, what |
---|
203 | form we want to be rendered in this viewlet. We tell the name of |
---|
204 | this form and not its class or similar. |
---|
205 | |
---|
206 | The associated view, context, viewletmanager, etc. can be set as |
---|
207 | with regular viewlets. |
---|
208 | |
---|
209 | """ |
---|
210 | formview_name = None |
---|
211 | |
---|
212 | def update(self): |
---|
213 | self.form = getMultiAdapter((self.context, self.request), |
---|
214 | name=self.formview_name) |
---|
215 | self.form.update_form() |
---|
216 | if self.request.method == 'POST': |
---|
217 | #app = get_application(self.context) |
---|
218 | #self.__parent__.redirect(self.__parent__.url(obj=app)) |
---|
219 | pass |
---|
220 | |
---|
221 | def render(self): |
---|
222 | result = self.form.render() |
---|
223 | try: |
---|
224 | # strip all except the form part... |
---|
225 | result = re.match('^.+\(<form[^\>]+>.*</form>).+$', result, |
---|
226 | re.DOTALL).groups()[0] |
---|
227 | except: |
---|
228 | # except there is no such part... |
---|
229 | pass |
---|
230 | return result |
---|