1. Pierre-Yves David
  2. pyti-master

Commits

Pierre-Yves David  committed fe2cc4a

Code for index and menu

this is mostly intended as example of what it needed.

  • Participants
  • Parent commits ae34d9e
  • Branches default

Comments (0)

Files changed (7)

File data/cubes.pytimaster.css

View file
  • Ignore whitespace
 }
 
 a, a:active, a:visited, a:link{
-    text-decoration:none;
-    color:#009931;
+    text-decoration: none;
+    color: #009931;
 }
 
 a:hover{
 /*----INDEX -----*/
 
 #logo_typi{
-float:left;
 width:500px;
-height:500px;
+/*height:500px;*/
 background:url('logo_1.png') no-repeat;
 }
 
 #index_top{
-float:right;
 width:40%;
 margin-top:1.5em;
 }
 
 #index_content{
-float:right;
 width:40%;
 margin-top:1.5em;
 }
 
+ul#easy-menu {
+    background-color: green;
+}
 
+ul#easy-menu a {
+    color: white;
+}
 
 
+

File data/easy-menu.css

View file
  • Ignore whitespace
+#easy-menu {
+    font-weight = bolder;
+}
+
+#easy-menu li {
+    display: inline-block;
+    list-style-type: none;
+    background: none;
+}
+
+#easy-menu li img {
+    height: 2em;
+    width: 2em;
+}

File entities/__init__.py

View file
  • Ignore whitespace
     def dc_title(self):
         return self.target_id[:10]
 
+    def dc_long_title(self):
+        return (u'Target %s added for %s on %s with %s'
+                        % (self.dc_title(),
+                           self.project_version.dc_long_title(),
+                           'linux',
+                           self.python_version.dc_long_title()))
+
     @property
     def project_version(self):
         return self.for_project_version[0]
 
     @property
     def project(self):
-        return self.for_project_version[0].version_of[0]
+        return self.for_project_version[0].project
 
     @property
     def python_version(self):
         return self.for_python_version[0]
+
+
+
+class ProjectVersion(AnyEntity):
+
+    __regid__ = 'ProjectVersion'
+
+    @property
+    def project(self):
+        return self.version_of[0]
+
+    def dc_long_title(self):
+        return '%s-%s' % (self.project.dc_title(), self.dc_title())
+

File views.py

  • Ignore whitespace
-# copyright 2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr -- mailto:contact@logilab.fr
-#
-# This program is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with this program. If not, see <http://www.gnu.org/licenses/>.
-
-"""cubicweb-pytimaster views/forms/actions/components for web ui"""
-
-import json
-
-from logilab.common.decorators import monkeypatch
-
-from cubicweb import ValidationError
-from cubicweb.web import StatusResponse
-from cubicweb.web.views.baseviews import EntityView # XXX wrong import
-from cubicweb.web.views.urlrewrite import SimpleReqRewriter, rgx
-from cubicweb.view import StartupView
-from cubicweb.web.controller import Controller
-from cubicweb.selectors import anonymous_user, is_instance
-
-from cubicweb.web.facet import RQLPathFacet, RelationFacet
-
-### html User Interface
-##################################
-
-# Any TE,PR,V,PY,ST WHERE TE is ExecutionTarget, TE for_project_version V, V version_of PR, TE for_python_version PY, TE in_state ST
-
-class ProjectFacet(RQLPathFacet):
-
-    __regid__ = 'project-facet'
-    __select__ = is_instance('ExecutionTarget')
-    path = ['X for_project_version V', 'V version_of P', 'P name N']
-    filter_variable = 'P'
-    label_variable = 'N'
-
-class PythonFacet(RelationFacet):
-    __regid__ = 'python-facet'
-    __select__ = is_instance('ExecutionTarget')
-    rtype = 'for_python_version'
-    target_attr = 'name'
-
-
-### WEB service
-##################################
-
-
-
-class ETJsonViews(EntityView):
-
-    __regid__ = "json"
-    templatable = False
-    content_type = 'text/json'
-
-
-
-    def call(self):
-        root = []
-        for et in self.rset.entities(): # XXX use cell_Call logic)
-            root.append({
-                    'target-id': et.target_id,
-                    'project-name': et.project.name,
-                    'project-version': et.project_version.num,
-                    'platform': 'linux-debian',
-                    'platform-variant': 'vanillia',
-                    'python-version': et.python_version.name,
-                })
-        self.w(unicode(json.dumps(root, indent=True))) # XXX unicode should ne be required
-
-
-class SlaveAPIRewriter(SimpleReqRewriter):
-
-    rules = [
-            ('/list', dict(rql=r'Any X WHERE X is ExecutionTarget', vid='json')),
-            ]
-
-
-class _TargetActionController(Controller):
-
-    __regid__ = None
-
-    def publish(self, rset=None):  # doesn't like it
-
-        if not ('target' in self._cw.form):
-            raise StatusResponse('400', 'action and target argument required')
-
-        action = self.__regid__
-        target_id = self._cw.form['target']
-        self.debug('%s on %s', action, target_id)
-
-        rset = self._cw.execute('Any X WHERE X target_id %(ti)s, X is ExecutionTarget',
-                                {'ti': target_id})
-
-        if not rset:
-            raise StatusResponse('404', 'target not found: %r' % target_id)
-        assert len(rset) == 1
-        target = rset.get_entity(0,0)
-        iwf = target.cw_adapt_to('IWorkflowable')
-        try:
-            iwf.fire_transition(action)
-            self._cw.cnx.commit()
-        except ValidationError, ex:
-            self._cw.cnx.rollback()
-            raise StatusResponse('409', str(ex))
-        return "ok"
-
-# XXX ugly use url evaluator instead
-
-class ClaimController(_TargetActionController):
-    __regid__ = 'claim'
-
-class CompleteController(_TargetActionController):
-    __regid__ = 'complete'
-

File views/__init__.py

View file
  • Ignore whitespace
 # copyright 2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr -- mailto:contact@logilab.fr
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 2.1 of the License, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""cubicweb-pytimaster views/forms/actions/components for web ui"""
+
+import json
+
+from logilab.common.decorators import monkeypatch
+
+from cubicweb import ValidationError
+from cubicweb.web import StatusResponse
+from cubicweb.web.views.baseviews import EntityView # XXX wrong import
+from cubicweb.web.views.urlrewrite import SimpleReqRewriter, rgx
+from cubicweb.view import StartupView
+from cubicweb.web.controller import Controller
+from cubicweb.selectors import anonymous_user, is_instance
+
+from cubicweb.web.facet import RQLPathFacet, RelationFacet
+
+### html User Interface
+##################################
+
+# Any TE,PR,V,PY,ST WHERE TE is ExecutionTarget, TE for_project_version V, V version_of PR, TE for_python_version PY, TE in_state ST
+
+class ProjectFacet(RQLPathFacet):
+
+    __regid__ = 'project-facet'
+    __select__ = is_instance('ExecutionTarget')
+    path = ['X for_project_version V', 'V version_of P', 'P name N']
+    filter_variable = 'P'
+    label_variable = 'N'
+
+class PythonFacet(RelationFacet):
+    __regid__ = 'python-facet'
+    __select__ = is_instance('ExecutionTarget')
+    rtype = 'for_python_version'
+    target_attr = 'name'
+
+
+### WEB service
+##################################
+
+
+
+class ETJsonViews(EntityView):
+
+    __regid__ = "json"
+    templatable = False
+    content_type = 'text/json'
+
+
+
+    def call(self):
+        root = []
+        for et in self.rset.entities(): # XXX use cell_Call logic)
+            root.append({
+                    'target-id': et.target_id,
+                    'project-name': et.project.name,
+                    'project-version': et.project_version.num,
+                    'platform': 'linux-debian',
+                    'platform-variant': 'vanillia',
+                    'python-version': et.python_version.name,
+                })
+        self.w(unicode(json.dumps(root, indent=True))) # XXX unicode should ne be required
+
+
+class SlaveAPIRewriter(SimpleReqRewriter):
+
+    rules = [
+            ('/list', dict(rql=r'Any X WHERE X is ExecutionTarget', vid='json')),
+            ]
+
+
+class _TargetActionController(Controller):
+
+    __regid__ = None
+
+    def publish(self, rset=None):  # doesn't like it
+
+        if not ('target' in self._cw.form):
+            raise StatusResponse('400', 'action and target argument required')
+
+        action = self.__regid__
+        target_id = self._cw.form['target']
+        self.debug('%s on %s', action, target_id)
+
+        rset = self._cw.execute('Any X WHERE X target_id %(ti)s, X is ExecutionTarget',
+                                {'ti': target_id})
+
+        if not rset:
+            raise StatusResponse('404', 'target not found: %r' % target_id)
+        assert len(rset) == 1
+        target = rset.get_entity(0,0)
+        iwf = target.cw_adapt_to('IWorkflowable')
+        try:
+            iwf.fire_transition(action)
+            self._cw.cnx.commit()
+        except ValidationError, ex:
+            self._cw.cnx.rollback()
+            raise StatusResponse('409', str(ex))
+        return "ok"
+
+# XXX ugly use url evaluator instead
+
+class ClaimController(_TargetActionController):
+    __regid__ = 'claim'
+
+class CompleteController(_TargetActionController):
+    __regid__ = 'complete'
+

File views/index.py

View file
  • Ignore whitespace
 
 from cubicweb.web.views import startup
 
+import cwtags.tag as cwt
+
+def get_component(appobj, component_id, registry='components', **k):
+    component = appobj._cw.vreg[registry].select_or_none(
+        component_id, appobj._cw, rset=appobj.cw_rset, **k)
+    if component:
+        return component
+
+
 
 class PytiMasterIndexView(startup.ManageView):
     """Pyti Master index for public home page
         """front page / index view
         """
         if self._cw.user.is_anonymous():
-            self.display_page()
+            self.display_header()
             self.display_test()
-            self.display_content()
         else:
             super(PytiMasterIndexView, self).call()
 
-    def display_page(self):
+    def display_header(self):
         """Page
         """
         self._cw.add_css('hide.css')
         self.w(u'<div id="logo_typi">')
         self.w(u'</div>')
-        self.w(u'<div id="index_top">')
-        self.w(u'<h1>The python testing infrastructure</h1>')        
-        self.w(u'<h3>The python testing infrastructure is a Continuous Integration tool able to test python distributions availabe at PyPI against a set of tests, providing a set of metrics.</h3>')   
-        self.w(u'</div>')
 
-       
+        comp = get_component(self, 'easy-menu')
+        comp.render(w=self.w)
 
     def display_test(self):
         """calls news-mini-view to show last n publish test.
         #       'TE for_python_version PY, TE in_state ST ')
         #rset = self._cw.execute(rql)
         #self.wview('displaytest', rset, 'null')
+        rql = ('Any TE,PR,V,PY WHERE TE is ExecutionTarget, '
+               'TE for_project_version V, V version_of PR, '
+               'TE for_python_version PY, TE in_state ST, ST name "assigned"')
+        running_rset = self._cw.execute(rql)
+        rql = ('Any TE,PR,V,PY WHERE TE is ExecutionTarget, '
+               'TE for_project_version V, V version_of PR, '
+               'TE for_python_version PY, TE in_state ST, ST name "pending"')
+        pending_rset = self._cw.execute(rql)
 
-    def display_content(self):
-        """call the card with the wikiid = index
-        """
-        #rql = ('Any C WHERE C is Card, C wikiid %(wikiid)s')
-        #rset = self._cw.execute(rql, {'wikiid': 'index'})
-        self.w(u'<div id="index_content">')
-        #self.wview('primary', rset, 'null')
-        self.w(u'<h1>The python testing infrastructure</h1>')        
-        self.w(u'<h3>The python testing infrastructure is a Continuous Integration tool able to test python distributions availabe at PyPI against a set of tests, providing a set of metrics.</h3>')   
-        self.w(u'</div>')
+        rql = ('Any TE,PR,V,PY WHERE TE is ExecutionTarget, '
+               'TE for_project_version V, V version_of PR, '
+               'TE for_python_version PY, TE in_state ST, ST name "done", TRI to_state ST, TRI creation_date >= (today -1)')
+        done_rset = self._cw.execute(rql)
+
+
+        with cwt.p(self.w):
+            with cwt.a(self.w, href="#target-pending"):
+                self.w(self._cw._(u'%i running') % len(running_rset))
+            self.w(u', ')
+            with cwt.a(self.w, href="#target-running"):
+                self.w(self._cw._(u'%i pending') % len(pending_rset))
+            self.w(u', ')
+            with cwt.a(self.w, href="#target-done"):
+                self.w(self._cw._(u'%i done in the last 24h') % len(done_rset))
+
+        # running
+        with cwt.h3(self.w, id='target-running'):
+            self.w(self._cw._(u'%i Targets running') % len(running_rset))
+        rset =  running_rset
+
+        self.wview('table', rset, 'null')
+
+
+        # pending
+        with cwt.h3(self.w, id='target-pending'):
+            self.w(self._cw._(u'%i Targets pending') % len(pending_rset))
+
+        rset = pending_rset.limit(20)
+
+        self.wview('table', rset, 'null')
+        with cwt.a(self.w, href=self.build_url('executiontarget')):
+            self.w(_(u'view all pending target'))
+
+        # done
+        with cwt.h3(self.w, id='target-done'):
+            self.w(self._cw._(u'%i Targets done in the last 24h') % len(done_rset))
+        rset = done_rset.limit(20)
+        self.wview('table', rset, 'null')
+        with cwt.a(self.w, href=self.build_url('executiontarget')):
+            self.w(_(u'view all done target'))
 
 
 

File views/menu.py

View file
  • Ignore whitespace
+"""An easy way to write create menu
+"""
+
+from operator import attrgetter
+
+from cwtags import tag as cwt
+from cubicweb.view import Component
+from cubicweb.appobject import AppObject
+from cubicweb.selectors import yes
+
+_ = unicode
+
+
+### Core Code
+##########################
+
+class EasyMenu(Component):
+
+    __regid__ = 'easy-menu'
+
+    def call(self):
+        self._cw.add_css('easy-menu.css')
+        entries = self._cw.vreg['menu-entry'].possible_objects(self._cw)
+        entries = sorted(entries, key=attrgetter('order'))
+        w = self.w
+        with cwt.ul(w, id="easy-menu"):
+            for entry in entries:
+                attr = {}
+                icon = entry.icon()
+                if icon is not None:
+                    cwt.img(w, src=icon) # use proper css if possible
+                with cwt.li(w, **attr):
+                    attr = {}
+                    description = entry.description()
+                    if description is not None:
+                        attr['title'] = description
+                    with cwt.a(w, href=entry.url(), **attr):
+                        self.w(entry.label())
+
+
+class MenuEntry(AppObject):
+
+    __registry__ = 'menu-entry'
+    __abstract__ = True
+
+    order = 99
+
+    __select__ = yes('0.5')
+
+    def label(self):
+         raise NotImplementedError
+
+    def url(self):
+         raise NotImplementedError
+
+    def description(self):
+        return None
+
+    def icon(self):
+        return None
+
+### Pyti Entry
+##########################
+
+class StatusMenuEntry(MenuEntry):
+
+    __regid__ = 'status'
+
+    order = 1
+
+    def label(self):
+        return self._cw._('Status')
+
+    def description(self):
+        return self._cw._('Summary of the PyTI status')
+
+    def url(self):
+        return self._cw.build_url('status')
+
+    def icon(self):
+        return 'http://upload.wikimedia.org/wikipedia/commons/e/e2/Crystal_Clear_app_kchart.png'
+
+class AboutMenuEntry(MenuEntry):
+
+    __regid__ = 'about'
+
+    order = 25
+
+    def label(self):
+        return self._cw._('About')
+
+    def description(self):
+        return self._cw._('What is Pyti')
+
+    def url(self):
+        return u'http://pyti.readthedocs.org/'
+
+class JoinMenuEntry(MenuEntry):
+
+    __regid__ = 'join'
+
+    order = 30
+
+    def label(self):
+        return self._cw._('Join')
+
+    def description(self):
+        return self._cw._('How to Join the Pyti effort')
+
+    def url(self):
+        return u'http://pyti.readthedocs.org/'
+
+class ResultMenuEntry(MenuEntry):
+
+    __regid__ = 'result'
+
+    order = 20
+
+    def label(self):
+        return self._cw._('Result')
+
+    def description(self):
+        return self._cw._('See execution result')
+
+    def url(self):
+        return u'http://www.pyti.org'
+
+class WorkerMenuEntry(MenuEntry):
+
+    __regid__ = 'worker'
+
+    order = 10
+
+    def label(self):
+        return self._cw._('Workers')
+
+    def description(self):
+        return self._cw._('See registered Worker')
+
+    def url(self):
+        return self._cw.build_url('worker')
+
+class TargetMenuEntry(MenuEntry):
+
+    __regid__ = 'Target'
+
+    order = 5
+
+    def label(self):
+        return self._cw._('Targets')
+
+    def description(self):
+        return self._cw._('see all execution target')
+
+    def url(self):
+        return self._cw.build_url('executiontarget')