source: products/quintagroup.analytics/trunk/quintagroup/analytics/browser/views.py @ 3003

Last change on this file since 3003 was 2999, checked in by fenix, 14 years ago

added section with types without workflow

  • Property svn:eol-style set to native
File size: 18.1 KB
Line 
1from Acquisition import aq_base
2from zope.component import getUtility, getMultiAdapter, queryMultiAdapter
3
4from OFS.interfaces import IPropertyManager
5from Products.Five.browser import BrowserView
6from Products.CMFCore.utils import getToolByName
7from Products.CMFCore.interfaces import IFolderish
8from Products.Archetypes.interfaces import IBaseFolder
9from plone.portlets.interfaces import IPortletManager
10from plone.portlets.interfaces import IPortletAssignmentMapping
11from plone.portlets.interfaces import ILocalPortletAssignmentManager
12try:
13    from plone.portlets.interfaces import IPortletAssignmentSettings
14except ImportError:
15    "Before plon4 we don't have an annotation storage for settings."
16    IPortletAssignmentSettings = lambda assignment:{}
17
18from GChartWrapper import VerticalBarStack
19
20from quintagroup.analytics.config import COLORS, OTHER_TYPES, NO_WF_BIND
21
22class OwnershipByType(BrowserView):
23    MAX = 10
24    def __init__(self, context, request):
25        self.context = context
26        self.request = request
27        self.cat = getToolByName(self.context, 'portal_catalog')
28        self.users = None
29        self.total = None
30        self.types = None
31        self.data = {}
32
33    def getUsers(self):
34        if self.users is None:
35            index = self.cat._catalog.getIndex('Creator')
36            data = {}
37            for k in index._index.keys():
38                haslen = hasattr(index._index[k], '__len__')
39                if haslen:
40                    data[k] = len(index._index[k])
41                else:
42                    data[k] = 1
43            data = data.items()
44            data.sort(lambda a, b: a[1] - b[1])
45            data.reverse()
46            data = data[:self.MAX]
47            self.users = [i[0] for i in data]
48            self.total = [i[1] for i in data]
49        return self.users
50
51    def getTypes(self, all=False):
52        if self.types is None:
53            index = self.cat._catalog.getIndex('portal_type')
54            data = {}
55            for k in index._index.keys():
56                if not k:
57                    continue
58                haslen = hasattr(index._index[k], '__len__')
59                if haslen:
60                    data[k] = len(index._index[k])
61                else:
62                    data[k] = 1
63            data = data.items()
64            data.sort(lambda a, b: a[1] - b[1])
65            data.reverse()
66            self.types = [i[0] for i in data]
67        return all and self.types or self.types[:self.MAX]
68
69    def getContent(self, type_):
70        if type_ not in self.data:
71            data = self.data[type_] = []
72            for user in self.getUsers():
73                res = self.cat(portal_type=type_, Creator=user)
74                l = len(res)
75                if l == 0:
76                    data.append(0)
77                else:
78                    data.append(l)
79        return self.data[type_]
80
81    def getTotal(self):
82        return self.total
83
84    def getChart(self):
85        data = []
86        types = self.getTypes()
87        for type_ in types:
88            data.append(self.getContent(type_))
89        other = [self.getContent(t) for t in self.getTypes(all=True)[self.MAX:]]
90        data.append([sum(l) for l in zip(*other)])
91        max_value = max(self.getTotal())
92        chart = VerticalBarStack(data, encoding='text')
93        chart.title('Content ownership by type').legend(*(types+OTHER_TYPES))
94        chart.bar('a', 10, 0).legend_pos("b")
95        chart.color(*COLORS)
96        chart.size(800, 375).scale(0,max_value).axes('xy').label(*self.users)
97        chart.axes.type("y")
98        chart.axes.range(0,0,max_value)
99        return chart.img()
100
101
102class OwnershipByState(BrowserView):
103    MAX = 10
104    def __init__(self, context, request):
105        self.context = context
106        self.request = request
107        self.cat = getToolByName(self.context, 'portal_catalog')
108        self.users = None
109        self.states = None
110        self.total = None
111        self.data = {}
112
113    def getUsers(self):
114        if self.users is None:
115            index = self.cat._catalog.getIndex('Creator')
116            data = {}
117            for k in index._index.keys():
118                haslen = hasattr(index._index[k], '__len__')
119                if haslen:
120                    data[k] = len(index._index[k])
121                else:
122                    data[k] = 1
123            data = data.items()
124            data.sort(lambda a, b: a[1] - b[1])
125            data.reverse()
126            data = data[:self.MAX]
127            self.users = [i[0] for i in data]
128            self.total = [i[1] for i in data]
129        return self.users
130
131    def getStates(self):
132        if self.states is None:
133            index = self.cat._catalog.getIndex('review_state')
134            data = {}
135            for k in index._index.keys():
136                haslen = hasattr(index._index[k], '__len__')
137                if haslen:
138                    data[k] = len(index._index[k])
139                else:
140                    data[k] = 1
141            data = data.items()
142            data.sort(lambda a, b: a[1] - b[1])
143            data.reverse()
144            self.states = [i[0] for i in data]
145        return self.states
146
147    def getContent(self, type_):
148        if type_ not in self.data:
149            if NO_WF_BIND not in self.data:
150                self.data[NO_WF_BIND] = self.getTotal()
151            data = self.data[type_] = []
152            for user in self.getUsers():
153                res = self.cat(review_state=type_, Creator=user)
154                l = len(res)
155                if l == 0:
156                    data.append(0)
157                else:
158                    data.append(l)
159            if len(data) > 0:
160                self.data[NO_WF_BIND] = map(lambda t,d:t-d, self.data[NO_WF_BIND], data)
161        return self.data[type_]
162
163    def getNoWFContentTitle(self):
164        return NO_WF_BIND
165
166    def getNoWFContent(self):
167        return self.getContent(NO_WF_BIND)
168
169    def getTotal(self):
170        if self.total is None:
171            self.getUsers()
172        return self.total
173
174    def getChart(self):
175        data = []
176        for state in self.getStates():
177            data.append(self.getContent(state))
178        data.append(self.getNoWFContent())
179        max_value = max(self.getTotal())
180        chart = VerticalBarStack(data, encoding='text')
181        chart.title('Content ownership by state').legend(*self.states+[NO_WF_BIND])
182        chart.bar('a', 10, 0).legend_pos("b")
183        chart.color(*COLORS)
184        chart.size(800, 375).scale(0,max_value).axes('xy').label(*self.users)
185        chart.axes.type("y")
186        chart.axes.range(0,0,max_value)
187        return chart.img()
188
189
190class TypeByState(BrowserView):
191    MAX = 10
192    def __init__(self, context, request):
193        self.context = context
194        self.request = request
195        self.cat = getToolByName(self.context, 'portal_catalog')
196        self.types = None
197        self.states = None
198        self.total = None
199        self.data = {}
200
201    def getTypes(self):
202        if self.types is None:
203            index = self.cat._catalog.getIndex('portal_type')
204            data = {}
205            for k in index._index.keys():
206                if not k:
207                    continue
208                haslen = hasattr(index._index[k], '__len__')
209                if haslen:
210                    data[k] = len(index._index[k])
211                else:
212                    data[k] = 1
213            data = data.items()
214            data.sort(lambda a, b: a[1] - b[1])
215            data.reverse()
216            self.types = [i[0] for i in data[:self.MAX]]
217            self.total = [i[1] for i in data[:self.MAX]]
218        return self.types
219
220    def getStates(self):
221        if self.states is None:
222            index = self.cat._catalog.getIndex('review_state')
223            data = {}
224            for k in index._index.keys():
225                haslen = hasattr(index._index[k], '__len__')
226                if haslen:
227                    data[k] = len(index._index[k])
228                else:
229                    data[k] = 1
230            data = data.items()
231            data.sort(lambda a, b: a[1] - b[1])
232            data.reverse()
233            self.states = [i[0] for i in data]
234        return self.states
235
236    def getContent(self, state):
237        if state not in self.data:
238            if NO_WF_BIND not in self.data:
239                self.data[NO_WF_BIND] = self.getTotal()
240            data = self.data[state] = []
241            for type_ in self.getTypes():
242                res = self.cat(portal_type=type_, review_state=state)
243                l = len(res)
244                if l == 0:
245                    data.append(0)
246                else:
247                    data.append(l)
248            if len(data) > 0:
249                self.data[NO_WF_BIND] = map(lambda t,d:t-d, self.data[NO_WF_BIND], data)
250        return self.data[state]
251
252    def getTotal(self):
253        if self.total is None:
254            self.getTypes()
255        return self.total
256
257    def getNoWFContentTitle(self):
258        return NO_WF_BIND
259
260    def getNoWFContent(self):
261        return self.getContent(NO_WF_BIND)
262
263    def getChart(self):
264        data = []
265        for state in self.getStates():
266            data.append(self.getContent(state))
267        data.append(self.getContent(NO_WF_BIND))
268        max_value = max(self.getTotal())
269        chart = VerticalBarStack(data, encoding='text')
270        chart.title('Content type by state').legend(*self.states+[NO_WF_BIND])
271        chart.bar('a', 10, 0).legend_pos("b")
272        chart.color(*COLORS)
273        chart.size(800, 375).scale(0,max_value).axes('xy').label(*self.types)
274        chart.axes.type("y")
275        chart.axes.range(0,0,max_value)
276        return chart.img()
277
278
279class LegacyPortlets(BrowserView):
280    def __init__(self, context, request):
281        self.context = context
282        self.request = request
283        self.total = None
284        self.DEBUG = False
285        self.expressions = set()
286
287    def _getInfo(self, obj):
288        href = obj.absolute_url()
289        path = '/'.join(obj.getPhysicalPath())
290        info = {
291            'path': path,
292            'href': href,
293            'left_slots': None,
294            'right_slots': None,
295        }
296        if IPropertyManager.providedBy(obj):
297            obj = aq_base(obj)
298            if obj.hasProperty('left_slots'):
299                info['left_slots'] = obj.getProperty('left_slots')
300                self.expressions = self.expressions.union(set(info['left_slots']))
301            if obj.hasProperty('right_slots'):
302                info['right_slots'] = obj.getProperty('right_slots')
303                self.expressions = self.expressions.union(set(info['right_slots']))
304        return info
305
306    def _walk(self, obj, level=-1):
307        yield self._getInfo(obj)
308        if level != 0 and (IFolderish.providedBy(obj) or IBaseFolder.providedBy(obj)):
309            for v in obj.contentValues():
310                for i in self._walk(v, level-1):
311                    yield i
312
313    def getPortlets(self):
314        level = self.request.form.get('level', 1)
315        level = int(level)
316        infos = []
317        for i in self._walk(self.context, level):
318            if self.DEBUG or i['left_slots'] is not None or i['right_slots'] is not None:
319                infos.append(i)
320        self.total = len(infos)
321        return infos
322
323    def getTotal(self):
324        return self.total
325
326    def getAllPortletExpressions(self):
327        exprs = []
328        for name in self.expressions:
329            name = name.split('|')[0]
330            if not '/macros/' in name:
331                name = name.split('/')[-1]
332            name = name.strip()
333            if name not in exprs:
334                exprs.append(name)
335        exprs.sort()
336        return exprs
337
338class PropertiesStats(BrowserView):
339    def __init__(self, context, request):
340        self.context = context
341        self.request = request
342        self.total = None
343        self.DEBUG = False
344        self.expressions = set()
345        self.proplist = []
346        self.propname = self.request.form.get('propname') or ""
347
348    def _getInfo(self, obj):
349
350        href = obj.absolute_url()
351        path = '/'.join(obj.getPhysicalPath())
352        info = {
353            'path': path,
354            'href': href,
355            'slots': None,
356        }
357        if IPropertyManager.providedBy(obj):
358            obj = aq_base(obj)
359            self.proplist.extend([i for i in obj.propertyIds() if i not in self.proplist])
360            if obj.hasProperty(self.propname):
361                info['slots'] = obj.getProperty(self.propname)
362                if isinstance(info['slots'], int):
363                    info['slots'] = str(info['slots'])
364                if not isinstance(info['slots'], basestring):
365                    self.expressions = self.expressions.union(set(info['slots']))
366                else:
367                    self.expressions = self.expressions.union(set([info['slots']]))
368        return info
369
370    def _walk(self, obj, level=-1):
371        yield self._getInfo(obj)
372        if level != 0 and (IFolderish.providedBy(obj) or IBaseFolder.providedBy(obj)):
373            for v in obj.contentValues():
374                for i in self._walk(v, level-1):
375                    yield i
376
377    def getPropsList(self):
378        level = self.request.form.get('level', 1)
379        level = int(level)
380        infos = []
381        for i in self._walk(self.context, level):
382            if self.DEBUG or i['slots'] is not None:
383                infos.append(i)
384        self.total = len(infos)
385        return infos
386
387    def getTotal(self):
388        return self.total
389
390    def getAllPortletExpressions(self):
391        exprs = []
392        for name in self.expressions:
393            name = name.strip()
394            if name not in exprs:
395                exprs.append(name)
396        #exprs.sort()
397        return exprs
398
399class PortletsStats(BrowserView):
400    def __init__(self, context, request):
401        self.context = context
402        self.request = request
403        self.total = None
404        self.DEBUG = False
405        self.expressions = set()
406        self.proplist = []
407        self.propname = self.request.form.get('propname') or ""
408
409    def getAssignmentMappingUrl(self, context, manager):
410        baseUrl = str(getMultiAdapter((context, self.request), name='absolute_url'))
411        return '%s/++contextportlets++%s' % (baseUrl, manager.__name__)
412
413    def getAssignmentsForManager(self, context, manager):
414        assignments = getMultiAdapter((context, manager), IPortletAssignmentMapping)
415        return assignments.values()
416
417    def getPortletsMapping(self, context):
418        leftcolumn = getUtility(IPortletManager, name=u'plone.leftcolumn', context=context)
419        rightcolumn = getUtility(IPortletManager, name=u'plone.rightcolumn', context=context)
420        leftmapping = getMultiAdapter((context, leftcolumn,), IPortletAssignmentMapping)
421        rightmapping = getMultiAdapter((context, rightcolumn,), IPortletAssignmentMapping)
422        return (leftmapping, rightmapping)
423
424    def getLocalPortletsManager(self, context):
425        leftcolumn = getUtility(IPortletManager, name='plone.leftcolumn', context=context)
426        rightcolumn = getUtility(IPortletManager, name='plone.rightcolumn', context=context)
427        leftmanager = getMultiAdapter((context, leftcolumn,), ILocalPortletAssignmentManager)
428        rightmanager = getMultiAdapter((context, rightcolumn,), ILocalPortletAssignmentManager)
429        return (leftmanager, rightmanager)
430
431    def getPortletsManager(self, context):
432        left = getUtility(IPortletManager, name='plone.leftcolumn', context=context)
433        right = getUtility(IPortletManager, name='plone.rightcolumn', context=context)
434        return (left, right)
435
436    def portlets_for_assignments(self, assignments, manager, base_url):
437        data = []
438        for idx in range(len(assignments)):
439            name = assignments[idx].__name__
440
441            editview = queryMultiAdapter(
442                (assignments[idx], self.request), name='edit', default=None)
443
444            if editview is None:
445                editviewName = ''
446            else:
447                editviewName = '%s/%s/edit' % (base_url, name)
448
449            settings = IPortletAssignmentSettings(assignments[idx])
450
451            data.append({
452                'title'      : assignments[idx].title,
453                'editview'   : editviewName,
454                'visible'    : settings.get('visible', True),
455                })
456        return data
457
458    def getPortlets(self, context, mapping, manager):
459        #import pdb; pdb.set_trace()
460        return mapping.keys()
461
462    def _getInfo(self, obj):
463        href = obj.absolute_url()
464        path = '/'.join(obj.getPhysicalPath())
465        info = {
466            'path': path,
467            'href': href,
468            'left_slots': None,
469            'right_slots': None,
470        }
471        left, right = self.getPortletsManager(obj)
472        #leftmapping, rightmapping = self.getPortletsMapping(obj)
473        #leftmanager, rightmanager = self.getLocalPortletsManager(obj)
474        #info['left_slots'] = self.getPortlets(obj, leftmapping, leftmanager)
475        #info['right_slots'] = self.getPortlets(obj, rightmapping, rightmanager)
476        lass = self.getAssignmentsForManager(obj, left)
477        rass = self.getAssignmentsForManager(obj, right)
478        lurl = self.getAssignmentMappingUrl(obj, left)
479        rurl = self.getAssignmentMappingUrl(obj, right)
480        plass = self.portlets_for_assignments(lass, left, lurl)
481        prass = self.portlets_for_assignments(rass, right, rurl)
482        #print obj, plass, prass
483        info['left_slots'] = plass #[i['title'] for i in plass]
484        info['right_slots'] = prass #[i['title'] for i in prass]
485        return info
486
487    def _walk(self, obj, level=-1):
488        try:
489            yield self._getInfo(obj)
490        except:
491            pass
492        if level != 0 and (IFolderish.providedBy(obj) or IBaseFolder.providedBy(obj)):
493            for v in obj.contentValues():
494                for i in self._walk(v, level-1):
495                    yield i
496
497    def getPropsList(self):
498        level = self.request.form.get('level', 1)
499        level = int(level)
500        infos = []
501        for i in self._walk(self.context, level):
502            if self.DEBUG or i['left_slots'] is not None or i['right_slots'] is not None:
503                infos.append(i)
504        self.total = len(infos)
505        return infos
506
507    def getTotal(self):
508        return self.total
509
510    def getAllPortletExpressions(self):
511        exprs = []
512        for name in self.expressions:
513            name = name.strip()
514            if name not in exprs:
515                exprs.append(name)
516        #exprs.sort()
517        return exprs
Note: See TracBrowser for help on using the repository browser.