~schooltool-owners/schooltool.peas/packaging

« back to all changes in this revision

Viewing changes to src/schooltool/peas/note/browser/note.py

  • Committer: Douglas Cerna
  • Date: 2015-02-17 08:43:21 UTC
  • mfrom: (9.1.28 schooltool.peas)
  • Revision ID: douglascerna@yahoo.com-20150217084321-l9mgb9oifyhjgs93
New release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# SchoolTool - common information systems platform for school administration
 
3
# Copyright (c) 2015 Shuttleworth Foundation
 
4
#
 
5
# This program is free software; you can redistribute it and/or modify
 
6
# it under the terms of the GNU General Public License as published by
 
7
# the Free Software Foundation; either version 2 of the License, or
 
8
# (at your option) any later version.
 
9
#
 
10
# This program is distributed in the hope that it will be useful,
 
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
# GNU General Public License for more details.
 
14
#
 
15
# You should have received a copy of the GNU General Public License
 
16
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
#
 
18
"""
 
19
Note views
 
20
"""
 
21
 
 
22
from zope.browserpage.viewpagetemplatefile import ViewPageTemplateFile
 
23
from zope.cachedescriptors.property import Lazy
 
24
from zope.component import queryMultiAdapter
 
25
from zope.container.interfaces import INameChooser
 
26
from zope.i18n import translate
 
27
from zope.security.proxy import removeSecurityProxy
 
28
from zope.traversing.browser.absoluteurl import absoluteURL
 
29
 
 
30
from z3c.form import button
 
31
from z3c.form import field
 
32
from z3c.form import form
 
33
from z3c.form import widget
 
34
from z3c.form.interfaces import DISPLAY_MODE
 
35
from zc.table.column import GetterColumn
 
36
 
 
37
from schooltool.skin import flourish
 
38
from schooltool.common import getResourceURL
 
39
from schooltool.common.inlinept import InheritTemplate
 
40
from schooltool import table
 
41
from schooltool.common import SchoolToolMessage as STMessage
 
42
from schooltool.peas.note.interfaces import INoteContainer
 
43
from schooltool.peas.note.interfaces import INote
 
44
from schooltool.peas.note.note import Note
 
45
# XXX: remove this once the ARK changes get into core
 
46
from schooltool.fee.browser.section import is_student
 
47
from schooltool.person.interfaces import IPerson
 
48
 
 
49
 
 
50
class PersonNotesViewlet(flourish.viewlet.Viewlet):
 
51
 
 
52
    template = ViewPageTemplateFile('templates/personnotes.pt')
 
53
 
 
54
    @property
 
55
    def canModify(self):
 
56
        return flourish.canEdit(self.notes)
 
57
 
 
58
    @Lazy
 
59
    def notes(self):
 
60
        return INoteContainer(self.context)
 
61
 
 
62
    def render(self, *args, **kw):
 
63
        if is_student(self.context):
 
64
            return self.template(*args, **kw)
 
65
        return ''
 
66
 
 
67
 
 
68
def edit_cell_formatter(value, item, formatter):
 
69
    principal = IPerson(formatter.request.principal, None)
 
70
    if principal is None or principal not in item.editors:
 
71
        return ''
 
72
    template = '''
 
73
      <a class="modify" href="%(edit_url)s" title="%(link_title)s">
 
74
        <img src="%(edit_icon_url)s" alt="%(edit_title)s" />
 
75
      </a>'''
 
76
    request = formatter.request
 
77
    library = 'schooltool.skin.flourish'
 
78
    item_url = absoluteURL(item, request)
 
79
    person_url = absoluteURL(IPerson(item.__parent__), request)
 
80
    return template % {
 
81
        'edit_url': '%s/edit.html?camefrom=%s' % (item_url, person_url),
 
82
        # XXX translate
 
83
        'link_title': 'Edit this note',
 
84
        'edit_icon_url': getResourceURL(library, 'edit-icon.png', request),
 
85
        'edit_title': translate(STMessage('Edit'), context=request),
 
86
    }
 
87
 
 
88
 
 
89
def category_cell_formatter(value, item, formatter):
 
90
    vocabulary = INote['category'].vocabulary
 
91
    try:
 
92
        term = vocabulary.getTermByToken(value)
 
93
        return term.title
 
94
    except (LookupError,):
 
95
        return ''
 
96
 
 
97
 
 
98
class DateColumn(table.column.DateColumn):
 
99
 
 
100
    def cell_formatter(self, maybe_date, item, formatter):
 
101
        view = queryMultiAdapter((maybe_date, formatter.request),
 
102
                                 name='shortDate',
 
103
                                 default=lambda: '')
 
104
        return view()
 
105
 
 
106
 
 
107
class NoteContainerTable(table.ajax.Table):
 
108
 
 
109
    @property
 
110
    def visible_column_names(self):
 
111
        result = ['action', 'date', 'editors', 'category', 'title']
 
112
        if not self.view.canModify:
 
113
            result = result[1:]
 
114
        return result
 
115
 
 
116
    def sortOn(self):
 
117
        return (('date', False), ('editors', False))
 
118
 
 
119
    def columns(self):
 
120
        actions = self.getActionColumns()
 
121
        date = DateColumn(
 
122
            name='date',
 
123
            title=STMessage('Date'),
 
124
            getter=lambda i, f: i.date,
 
125
            subsort=True)
 
126
        editors = GetterColumn(
 
127
            name='editors',
 
128
            # XXX: translate
 
129
            title=u'Author',
 
130
            getter=lambda i, f: ' '.join([removeSecurityProxy(e).title
 
131
                                          for e in i.editors]),
 
132
            subsort=True)
 
133
        category = GetterColumn(
 
134
            name='category',
 
135
            title=u'Category',
 
136
            getter=lambda i, f: i.category,
 
137
            cell_formatter=category_cell_formatter)
 
138
        title = GetterColumn(
 
139
            name='title',
 
140
            title=STMessage('Title'),
 
141
            getter=lambda i, f: i.title,
 
142
            cell_formatter=table.table.url_cell_formatter)
 
143
        return actions + [date, editors, category, title]
 
144
 
 
145
    def getActionColumns(self):
 
146
        if self.view.canModify:
 
147
            return [
 
148
                GetterColumn(
 
149
                    name='action',
 
150
                    title=STMessage('Edit'),
 
151
                    getter=lambda i, f: i,
 
152
                    cell_formatter=edit_cell_formatter)
 
153
            ]
 
154
        return []
 
155
 
 
156
    def updateFormatter(self):
 
157
        if self._table_formatter is None:
 
158
            self.setUp(table_formatter=self.table_formatter,
 
159
                       batch_size=self.batch_size,
 
160
                       prefix=self.__name__,
 
161
                       css_classes={'table': 'data notes'})
 
162
 
 
163
 
 
164
class NoteAddView(flourish.form.AddForm):
 
165
 
 
166
    template = InheritTemplate(flourish.page.Page.template)
 
167
    label = None
 
168
    # XXX translate
 
169
    legend = u'Note Information'
 
170
    fields = field.Fields(INote).omit('editors')
 
171
    factory = Note
 
172
 
 
173
    @Lazy
 
174
    def person(self):
 
175
        return IPerson(self.context)
 
176
 
 
177
    @property
 
178
    def title(self):
 
179
        return self.person.title
 
180
 
 
181
    def updateActions(self):
 
182
        super(NoteAddView, self).updateActions()
 
183
        self.actions['add'].addClass('button-ok')
 
184
        self.actions['cancel'].addClass('button-cancel')
 
185
 
 
186
    @button.buttonAndHandler(STMessage('Submit'), name='add')
 
187
    def handleAdd(self, action):
 
188
        super(NoteAddView, self).handleAdd.func(self, action)
 
189
 
 
190
    @button.buttonAndHandler(STMessage('Cancel'))
 
191
    def handleCancel(self, action):
 
192
        self.request.response.redirect(self.nextURL())
 
193
 
 
194
    def nextURL(self):
 
195
        return '%s?active_accordion=6' % absoluteURL(self.person, self.request)
 
196
 
 
197
    def create(self, data):
 
198
        obj = self.factory()
 
199
        form.applyChanges(self, obj, data)
 
200
        return obj
 
201
 
 
202
    def add(self, obj):
 
203
        chooser = INameChooser(self.context)
 
204
        name = chooser.chooseName(u'', obj)
 
205
        self.context[name] = obj
 
206
        person = IPerson(self.request.principal, None)
 
207
        if person is not None:
 
208
            obj.editors.add(removeSecurityProxy(person))
 
209
 
 
210
 
 
211
AddNoteDefaultDate = widget.ComputedWidgetAttribute(
 
212
    lambda adapter: adapter.request.util.today,
 
213
    view=NoteAddView,
 
214
    field=INote['date']
 
215
    )
 
216
 
 
217
 
 
218
class NoteEditView(flourish.form.Form, form.EditForm):
 
219
 
 
220
    template = InheritTemplate(flourish.page.Page.template)
 
221
    content_template = ViewPageTemplateFile('templates/note_form.pt')
 
222
    # XXX: translate
 
223
    legend = 'Note Information'
 
224
    fields = field.Fields(INote).omit('editors')
 
225
 
 
226
    @Lazy
 
227
    def person(self):
 
228
        return IPerson(self.context.__parent__)
 
229
 
 
230
    @property
 
231
    def title(self):
 
232
        return self.person.title
 
233
 
 
234
    def update(self):
 
235
        form.EditForm.update(self)
 
236
 
 
237
    def updateActions(self):
 
238
        super(NoteEditView, self).updateActions()
 
239
        self.actions['submit'].addClass('button-ok')
 
240
        self.actions['cancel'].addClass('button-cancel')
 
241
 
 
242
    def nextURL(self):
 
243
        try:
 
244
            return self.request['camefrom']
 
245
        except (KeyError,):
 
246
            return '%s?active_accordion=6' % absoluteURL(self.person,
 
247
                                                         self.request)
 
248
 
 
249
    @button.buttonAndHandler(STMessage('Submit'), name='submit')
 
250
    def handle_submit(self, action):
 
251
        super(NoteEditView, self).handleApply.func(self, action)
 
252
        if (self.status == self.successMessage or
 
253
           self.status == self.noChangesMessage):
 
254
            self.request.response.redirect(self.nextURL())
 
255
 
 
256
    @button.buttonAndHandler(STMessage('Cancel'), name='cancel')
 
257
    def handle_cancel(self, action):
 
258
        self.request.response.redirect(self.nextURL())
 
259
 
 
260
 
 
261
class NoteActionsLinks(flourish.page.RefineLinksViewlet):
 
262
 
 
263
    pass
 
264
 
 
265
 
 
266
class NoteDeleteLink(flourish.page.LinkViewlet):
 
267
 
 
268
    @property
 
269
    def url(self):
 
270
        return '%s/delete.html?delete.%s&CONFIRM' % (
 
271
            absoluteURL(self.context.__parent__, self.request),
 
272
            self.context.__name__.encode('utf-8'))
 
273
 
 
274
 
 
275
class NoteContainerDeleteView(flourish.containers.ContainerDeleteView):
 
276
 
 
277
    @Lazy
 
278
    def person(self):
 
279
        return IPerson(self.context)
 
280
 
 
281
    def nextURL(self):
 
282
        if 'CONFIRM' in self.request:
 
283
            return '%s?active_accordion=6' % absoluteURL(self.person,
 
284
                                                         self.request)
 
285
        return flourish.containers.ContainerDeleteView.nextURL(self)
 
286
 
 
287
 
 
288
class NoteView(flourish.page.Page):
 
289
 
 
290
    @property
 
291
    def title(self):
 
292
        return self.context.__parent__.__parent__.title
 
293
 
 
294
 
 
295
class NoteDetails(flourish.form.FormViewlet):
 
296
 
 
297
    template = ViewPageTemplateFile('templates/note.pt')
 
298
    fields = field.Fields(INote).omit('editors')
 
299
    mode = DISPLAY_MODE
 
300
 
 
301
    @property
 
302
    def canModify(self):
 
303
        return flourish.canEdit(self.notes)
 
304
 
 
305
    @Lazy
 
306
    def notes(self):
 
307
        return self.context.__parent__
 
308
 
 
309
    @Lazy
 
310
    def person(self):
 
311
        return self.context.__parent__.__parent__
 
312
 
 
313
    def done_link(self):
 
314
        return '%s?active_accordion=6' % absoluteURL(self.person, self.request)