Blame Scripts/CentOS-Web/Apps/page.py

cc10e6
#!/usr/bin/python
cc10e6
#
8c93bb
# Apps.page -- This module encapsulates the page layout of web
8c93bb
# applications.
cc10e6
#
8f6ee0
# Copyright (C) 2011 The CentOS Project
cc10e6
#
cc10e6
# This program is free software; you can redistribute it and/or modify
cc10e6
# it under the terms of the GNU General Public License as published by
cc10e6
# the Free Software Foundation; either version 2 of the License, or (at
cc10e6
# your option) any later version.
cc10e6
#
cc10e6
# This program is distributed in the hope that it will be useful, but
cc10e6
# WITHOUT ANY WARRANTY; without even the implied warranty of
cc10e6
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
cc10e6
# General Public License for more details.
cc10e6
#
cc10e6
# You should have received a copy of the GNU General Public License
cc10e6
# along with this program; if not, write to the Free Software
cc10e6
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
cc10e6
#
cc10e6
# ----------------------------------------------------------------------
cc10e6
# $Id$
cc10e6
# ----------------------------------------------------------------------
cc10e6
cc10e6
import os
cc10e6
import cgi
cc10e6
import cgitb; cgitb.enable()
8f6ee0
8c93bb
from Apps import xhtml
8c93bb
8c93bb
class Layout(xhtml.Strict):
cffc47
    """Xhtml page modeling."""
8f6ee0
8f6ee0
8f6ee0
    def __init__(self):
8f6ee0
        """Initialize page data."""
8f6ee0
        self.qs = cgi.parse_qs(os.environ['QUERY_STRING'])
8f6ee0
        self.name = 'Home'
8f6ee0
        self.title = 'The CentOS Project'
8f6ee0
        self.description = 'Community Enterprise Operating System'
8f6ee0
        self.keywords = 'centos, project, community, enterprise, operating system'
8f6ee0
        self.copyright = '2009-2011 The CentOS Project. All rights reserved.'
8f6ee0
        self.language = 'en'
8f6ee0
8f6ee0
8c93bb
    def preamble(self):
8f6ee0
        """Return XHTML code of page preamble.
cc10e6
8f6ee0
        The page preamble sets the document type definition required
8f6ee0
        by the XHTML standard.
cc10e6
8f6ee0
        """
8f6ee0
        output = '' + "\n"
8f6ee0
        output += '
8f6ee0
        output += ' '*4 + 'PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"' + "\n"
8f6ee0
        output += ' '*4 + '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' + "\n"
cc10e6
8f6ee0
        return output
cc10e6
cc10e6
8c93bb
    def logo(self):
8f6ee0
        """Returns XHTML code of page logo.
cc10e6
8f6ee0
        The page logo is displayed on the top-left corner of the page.
8f6ee0
        We use this area to show The CentOS Logo, the main visual
8f6ee0
        representation of The CentOS Project. In order to print the
8f6ee0
        page logo correctly, the image related must be 78 pixels of
8f6ee0
        height.
7e8dd3
8f6ee0
        """
8f6ee0
        attrs = []
8f6ee0
        attrs.append({'id': 'logo'})
8f6ee0
        attrs.append({'title': 'Community Enterprise Operating System', 'href': '/centos-web/'})
8f6ee0
        attrs.append({'src': '/centos-web-pub/Images/centos-logo.png', 'alt': 'CentOS'})
cc10e6
8c93bb
        return self.tag_div(attrs[0], [8,1], self.tag_a(attrs[1], [12,1], self.tag_img(attrs[2], [0,0]), 0), 1)
cc10e6
cc10e6
8c93bb
    def ads_google(self):
8f6ee0
        """Returns XHTML code of Google advertisement (468x60 pixels)."""
8f6ee0
        output = """
cc10e6
        
cc10e6
            Google Advertisement
cc10e6
            <script type="text/javascript">
cc10e6
                google_ad_client = "pub-6973128787810819";
cc10e6
                google_ad_width = 468;
cc10e6
                google_ad_height = 60;
cc10e6
                google_ad_format = "468x60_as";
cc10e6
                google_ad_type = "text_image";
cc10e6
                google_ad_channel = "";
cc10e6
                google_color_border = "204c8d";
cc10e6
                google_color_bg = "345c97";
cc10e6
                google_color_link = "0000FF";
cc10e6
                google_color_text = "FFFFFF";
cc10e6
                google_color_url = "008000";
cc10e6
                //-->
cc10e6
            </script>
cc10e6
            
cc10e6
                src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
cc10e6
            </script>
cc10e6
        
cc10e6
cc10e6
        

8f6ee0
        """
8f6ee0
        return output
cc10e6
cc10e6
8c93bb
    def navibar_top(self):
8f6ee0
        """Returns XHTML code of top-level navigation bar. 
cc10e6
    
8f6ee0
        The top-level navigation bar organizes links to the web
8f6ee0
        application The CentOS Project makes use of. Links in the
8f6ee0
        top-level navigation bar remain always visible, no matter what
8f6ee0
        web application you be visiting.
cc10e6
8f6ee0
        Notice that web application differe one another and is not
8f6ee0
        convenient to point them all to this definition. Instead, a
8f6ee0
        specific definition for each web application will be created
8f6ee0
        (based on this definition) in order for them to give the
8f6ee0
        impression of being connected. In this process, the top-level
8f6ee0
        navigation bar is adapted to each web application
8f6ee0
        characteristics and the related tab is set as current.
cc10e6
8f6ee0
        """
8f6ee0
        names = ['Home', 'Wiki', 'Lists', 'Forums', 'Projects', 'Bugs', 'Docs', 'Downloads', 'Sponsors']
8f6ee0
        attrs = []
8f6ee0
        focus = self.name
cc10e6
8f6ee0
        for i in range(len(names)):
8c93bb
            if names[i].lower() == 'home':
8c93bb
                attrs.append({'href': '/centos-web/'})
8c93bb
            else:
8c93bb
                attrs.append({'href': '/centos-web/?app=' + names[i].lower()})
8f6ee0
8c93bb
        tabs = self.navibar_tabs(names, attrs, focus)
8c93bb
        tabs += self.separator()
8f6ee0
8f6ee0
        return tabs
8f6ee0
8f6ee0
8c93bb
    def navibar_tabs(self, names, attrs, focus=''):
8f6ee0
        """Returns navigation tabs.
8f6ee0
8f6ee0
        Arguments:
8f6ee0
8f6ee0
        names: List of tab names.
8f6ee0
8f6ee0
        attrs: List of dictionaries for each tab name inside the
8f6ee0
            `names' list. Dictionaries inside attrs argument contain
8f6ee0
            the XHTML link attributes (e.g., accesskey, title, and
8f6ee0
            href) used by tab names so they can be linkable once
8f6ee0
            rendered.
cc10e6
    
8f6ee0
        focus: Name of the tab marked as current. When no value is
8f6ee0
            passed to this argument the `Home' value is used as
8f6ee0
            default value.
cc10e6
    
8f6ee0
        """
8f6ee0
        navibar_tabs = ''
cc10e6
8f6ee0
        for i in range(len(names)):
8c93bb
            content = self.tag_span('', [0,0], str(names[i]))
8c93bb
            content = self.tag_a(attrs[i], [16,1], content)
8f6ee0
            if str(names[i]).lower() == focus.lower():
8c93bb
                content = self.tag_span({'class': 'current'}, [12,1], content, 1)
8f6ee0
            else:
8c93bb
                content = self.tag_span('', [12,1], content, 1)
8f6ee0
            navibar_tabs += content
cc10e6
8c93bb
        return self.tag_div({'class': 'tabs'}, [8,1], navibar_tabs, 1)
cc10e6
cc10e6
8c93bb
    def lastreleases(self, names=['6.0'], attrs=[{'href': '/centos-web/?p=releases&id=6.0'}]):
8f6ee0
        """Returns last-release information and related RSS link."""
8f6ee0
        releases = ''
7e8dd3
8c93bb
        title = self.tag_a({'href': '/centos-web/?p=releases'}, [0,0], 'Last Releases') + ':'
8c93bb
        title = self.tag_span({'class': 'title'}, [16,1], title)
cc10e6
8f6ee0
        for i in range(len(names)):
8c93bb
            link = self.tag_a(attrs[i], [20,1], names[i])
8f6ee0
            if i == len(names) - 1:
8c93bb
                span = self.tag_span({'class': 'last release'}, [16,1], link, 1) 
8f6ee0
            else:
8c93bb
                span = self.tag_span({'class': 'release'}, [16,1], link, 1) 
8f6ee0
            releases += span
8c93bb
        releases = self.tag_div({'class': 'left'}, [12,1], title + releases, 1)
cc10e6
8c93bb
        rsslink = self.tag_span('', [0,0], 'RSS')
8c93bb
        rsslink = self.tag_a({'href': '/centos-web/?print=rss', 'title': 'RSS'}, [20,1], rsslink)
8c93bb
        rsslink = self.tag_span({'class': 'rss'}, [16,1], rsslink, 1)
8c93bb
        rsslink = self.tag_div({'class': 'right'}, [12, 1], rsslink, 1)
7e8dd3
8c93bb
        return self.tag_div({'id': 'last-releases'}, [8,1], releases + rsslink, 1)
7e8dd3
cc10e6
8c93bb
    def appslinks(self):
8f6ee0
        """Returns application related links."""
8c93bb
        appslinks = self.userlinks()
8c93bb
        return self.tag_div({'id': 'appslinks'}, [8,1], appslinks, 1)
cc10e6
cc10e6
8c93bb
    def lastvisit(self):
8c93bb
        last_visit = self.tag_a({'href': '/centos-web/?p=lastvisit'}, [0,0], 'Your last visit was at')
8c93bb
        last_visit = self.tag_span({'class': 'title'}, [16, 1], last_visit)
8c93bb
        last_visit += self.tag_span({'class': 'datetime'}, [16, 1], '...')
8c93bb
        return self.tag_div({'class': 'lastvisit'}, [12, 1], last_visit, 1)
cc10e6
cc10e6
8c93bb
    def session(self):
8f6ee0
        """Returns information related to user's session."""
8f6ee0
        names = []
8f6ee0
        attrs = []
8f6ee0
        session = ''
8f6ee0
8c93bb
        if 'app' in self.qs:
8c93bb
            app = 'app=' + self.qs['app'][0].lower() + '&'
8c93bb
        else:
8c93bb
            app = ''
8c93bb
8f6ee0
        names.append('Lost your password?')
8c93bb
        attrs.append({'href': '/centos-web/?' + app + 'p=lostpwd'})
8f6ee0
        names.append('Register')
8c93bb
        attrs.append({'href': '/centos-web/?' + app + 'p=register'})
8f6ee0
        names.append('Login')
8c93bb
        attrs.append({'href': '/centos-web/?' + app + 'p=login'})
8f6ee0
8f6ee0
        for i in range(len(names)):
8c93bb
            output = self.tag_a(attrs[i], [20,1], str(names[i]), 0)
8f6ee0
            if i == len(names) - 1:
8c93bb
                output = self.tag_span({'class': 'last'}, [16,1], output, 1)
8f6ee0
            else:
8c93bb
                output = self.tag_span('', [16,1], output, 1)
8f6ee0
            session += output
8f6ee0
8c93bb
        return self.tag_div({'class': 'session'}, [12,1], session, 1)
cc10e6
cc10e6
8c93bb
    def trail(self, names=['None'], attrs=[{'href': '/centos-web/'}]):
8f6ee0
        """Returns page trails (a.k.a. breadcrumbs).
cc10e6
    
8f6ee0
        The page breadcrumbs record the last pages visited inside the
8f6ee0
        current web application. Notice that page breadcrumbs are
8f6ee0
        user-specific information, so it isn't possible to implement
8f6ee0
        them until a way to manage user sessions be implemeneted
8f6ee0
        inside `centos-web.cgi' script. Until then, keep the tag
8f6ee0
        construction commented and return an empty value.
8f6ee0
8f6ee0
        """
8f6ee0
        links = ''
8f6ee0
8f6ee0
        for i in range(len(names)):
8f6ee0
            if i == len(names) - 1:
8c93bb
                content = self.tag_span({'class':'last'}, [16,1], self.tag_a(attrs[i], [20, 1], names[i]), 1)
8f6ee0
            else:
8c93bb
                content = self.tag_span('', [16,1], self.tag_a(attrs[i], [20, 1], names[i], 0), 1)
cffc47
            links += content
cc10e6
8c93bb
        return self.tag_div({'class': 'trail'}, [12,1], links, 1)
cc10e6
cc10e6
8c93bb
    def userlinks(self):
8f6ee0
        """Returns user links.
cc10e6
8f6ee0
        Arguments:
cc10e6
8f6ee0
        names: List of links you want to have.
cc10e6
8f6ee0
        attrs: List of dictionaries with link attributes. In order for
8f6ee0
            links to be built correctly, both names and attrs lists
8f6ee0
            must coincide their indexes.
cc10e6
8f6ee0
        The user links are specific to each web application. They are
8f6ee0
        shown in the right-top corner of the application navigation
8f6ee0
        bar, just over the application navigation tabs.
cc10e6
8f6ee0
        """
8c93bb
        userlinks = self.lastvisit()
8c93bb
        userlinks += self.session()
8c93bb
        userlinks += self.trail()
cc10e6
8c93bb
        return self.tag_div({'class': 'userlinks'}, [8,1], userlinks, 1)
cc10e6
cc10e6
8c93bb
    def navibar_app(self, names=['Welcome'], attrs=[{'href':'/centos-web/?p=welcome'}], focus='Welcome'):
8f6ee0
        """Returns application's navigation bar."""
8f6ee0
8c93bb
        navibar_app = self.navibar_tabs(names, attrs, focus)
8c93bb
        navibar_app += self.separator({'class': 'page-line white'}, [8,1])
8f6ee0
8f6ee0
        return navibar_app
8f6ee0
 
cc10e6
8c93bb
    def separator(self, attrs={'class': 'page-line'}, indent=[16,1]):
8f6ee0
        """Returns a division line."""
8c93bb
        line = self.tag_hr({'style': 'display:none;'}, [0,0])
8c93bb
        line = self.tag_div(attrs, indent, line)
cc10e6
8c93bb
        return line
cc10e6
cc10e6
8c93bb
    def license(self):
8f6ee0
        """Retruns link to page license."""
8f6ee0
        license = 'Creative Commons Attribution-Share Alike 3.0 Unported License'
8c93bb
        license = self.tag_a({'href': 'http://creativecommons.org/licenses/by-sa/3.0/'}, [0,0], license) + '.'
cffc47
8f6ee0
        return license
cc10e6
cc10e6
8c93bb
    def metadata(self):
8f6ee0
        """Returns page metadata."""
8c93bb
        metadata = self.tag_meta({'http-equiv': 'content-type', 'content': 'text/html; charset=UTF-8'}, [4,1])
8c93bb
        metadata += self.tag_meta({'http-equiv': 'content-style-type', 'content': 'text/css'}, [4,0])
8c93bb
        metadata += self.tag_meta({'http-equiv': 'content-language', 'content': str(self.language)}, [4,1])
8c93bb
        metadata += self.tag_meta({'name': 'keywords', 'content': str(self.keywords)}, [4,0])
8c93bb
        metadata += self.tag_meta({'name': 'description', 'content': str(self.description)}, [4,1])
8c93bb
        metadata += self.tag_meta({'name': 'copyright', 'content': 'Copyright © ' + str(self.copyright)}, [4,0])
8c93bb
        metadata += self.tag_title('', [4,1], self.title)
8c93bb
        metadata += self.tag_link({'href': '/centos-web-pub/stylesheet.css','rel': 'stylesheet', 'type': 'text/css'}, [4,0])
8c93bb
        metadata += self.tag_link({'href': '/centos-web-pub/Images/centos-fav.png', 'rel': 'shortcut icon', 'type': 'image/png'}, [4,1])
cc10e6
8c93bb
        return self.tag_head('', [0,1], metadata)
cc10e6
cc10e6
8c93bb
    def content(self, content='Empty Page.'):
8f6ee0
        """Returns page content."""
8f6ee0
        return content
cc10e6
cc10e6
8c93bb
    def admonition(self, title='Note', subtitle="", content=""):
cffc47
        """Returns page admonition.
cffc47
        
cffc47
        Arguments:
cffc47
cffc47
        title: Admonition's title.
cffc47
cffc47
        subtitle: Admonition's subtitle. The value of this argument is
cffc47
            concatenated on the right side of title using a colon (:)
cffc47
            as separator. Notice that this value is expanded inside
cffc47
            the 

tag and there is no need to introduce extra tags

cffc47
            here.
cffc47
cffc47
        content: Admonition's content. The values passed through this
cffc47
            arguments needs to be XHTML code returned from
cffc47
            `self.tag()'. Preferably, paragraphs (p), tables (table),
cffc47
            lists (ul, ol, dl) and pre-formatted texts (pre).
cffc47
cffc47
        """
cffc47
        if title == '':
cffc47
            return ''
cffc47
        else:
cffc47
            title = str(title.capitalize())
cffc47
cffc47
        if subtitle != '':
cffc47
            subtitle = ': ' + str(subtitle.capitalize())
cffc47
cffc47
        if content != '':
cffc47
            content = str(content)
cffc47
cffc47
        admonitions = ['Note', 'Tip', 'Important', 'Caution', 'Warning', 'Redirected', 'Success', 'Error']
cffc47
        
cffc47
        if title in admonitions:
cffc47
            attrs = {'class': 'admonition ' + title.lower()}
8c93bb
            image = self.tag_img({'src': '/centos-web-pub/Images/' + title.lower() + '.png', 'alt': title}, [16,1])
8c93bb
            title = self.tag_h3({'class': 'title'}, [16,1], title + subtitle, 0)
8c93bb
            output = image + title + content + self.separator()
cffc47
        else:
cffc47
            attrs = {'class': 'admonition unknown'}
8c93bb
            title = self.tag_h3({'class': 'title'}, [16,1], title + subtitle, 1)
cffc47
            output = title + content
cffc47
        
8c93bb
        return self.tag_div(attrs, [12,1], output, 1)
cffc47
cffc47
8c93bb
    def credits(self):
8f6ee0
        """Returns page credits."""
8c93bb
        copyright = self.tag_p({'class': 'copyright'}, [12,1], 'Copyright © ' + str(self.copyright))
8c93bb
        license = self.tag_p({'class': 'license'}, [12,1], 'This website is licensed under a ' + str(self.license()))
8c93bb
        credits = self.tag_img({'src': '/centos-web-pub/Images/top.png', 'alt': 'Top'}, [0,0])
8c93bb
        credits = self.tag_a({'title': 'Top', 'href': '#top'}, [16,1], credits)
8c93bb
        credits = self.tag_div({'class': 'top'}, [12,1], credits, 1)
8f6ee0
        credits = str(credits) + str(copyright) + str(license) 
8c93bb
        credits = self.tag_div({'class': 'credits'}, [8,1], credits, 1)
7e8dd3
8f6ee0
        return credits
cc10e6
cc10e6
8f6ee0
    def page(self):
8f6ee0
        """Returns page final output."""
8c93bb
        header = self.logo()
8c93bb
        header += self.ads_google()
8c93bb
        header += self.navibar_top()
8c93bb
        header += self.lastreleases()
8c93bb
        header += self.appslinks()
8c93bb
        header += self.navibar_app()
8c93bb
        header = self.tag_div({'id': 'page-header'}, [4,1], header, 1)
8c93bb
8c93bb
        body = self.content()
8c93bb
        body = self.tag_div({'id':'content'}, [8,1], body, 1)
8c93bb
        body = self.tag_div({'id':'page-body'}, [4,1], body, 1)
8c93bb
8c93bb
        footer = self.tag_div({'id': 'page-footer'}, [4,1], self.credits(), 1)
7e8dd3
    
8c93bb
        top = self.tag_a({'name':'top'}, [0,1])
8c93bb
        wrap = self.tag_div({'id': 'wrap'}, [0,1], header + body + footer, 1)
8c93bb
        body = self.tag_body('', [0,1], top + wrap)
7e8dd3
8c93bb
        html = self.preamble()
8c93bb
        html += self.tag_html({'xmlns': 'http://www.w3.org/1999/xhtml', 'dir': 'ltr', 
8f6ee0
                         'lang': str(self.language), 'xml:lang':
8c93bb
                         str(self.language)}, [0,1], self.metadata() +  body)
7e8dd3
8f6ee0
        return html
7e8dd3
7e8dd3
8f6ee0
    def main(self):
8f6ee0
        """The Xhtml code of a complete page."""
8f6ee0
        print self.page()