diff --git a/Scripts/CentOS-Web/Apps/page.py b/Scripts/CentOS-Web/Apps/page.py index 301f19f..f63bdd0 100755 --- a/Scripts/CentOS-Web/Apps/page.py +++ b/Scripts/CentOS-Web/Apps/page.py @@ -137,16 +137,84 @@ you can be aware of them. import cgi import cgitb; cgitb.enable() - from Apps import xhtml +qs = cgi.parse() + + +def qs_args( names={}): + """Returns query string arguments. + + The query string arguments are used to build links dynamically + and, this way, to create a browsable and logically organized web + environment. Such a construction generally needs to retrive some + of the values previously passed to the query string and add new + ones to it. + + names: A dictionary containing the variable name and value pair + used to build a new query string. + + When a variable is provied without a value, then its value is + retrived from the current query string. If a value isn't found + there neither, then the variable is removed from the new query + string. + + When a variable is provided with its value, then its value is used + to build the new query string. + + """ + output = '' + + names_keys = names.keys() + names_keys.sort() + for key in names_keys: + if names[key] == '': + if key in qs: + names[key] = qs[key][0] + else: + continue + if output == '': + output = '?' + else: + output += '&' + output += key + '=' + str(names[key]) + + return '/centos-web/' + output + + class Layout(xhtml.Strict): - """Page modeling.""" + """The Page Layout. + + The page layout is made by combining XHTML tags in specific ways. + These specific combinations make the page components which in turn + can be also combined. Some of these components can be reused and + others don't. The goal of this class is to define what such + components are and describe them well in order to understand how + to use them from application modules when building XHTML documents + dynamically. + + The page layout is initialized with a functional layout that can + be used as reference inside application modules, to create + variations of it. Generally, inside application packages, this + class is instantiated in a module named `page', variables are + reset and functions created in order to satisfy that application + needs. When you need to output one of the page components then you + use this class instantiated methods. When the method you need + doesn't exist in this class, then it is a good time for it to be + created, here ;). + + Notice that most methods defined in this class make direct use of + methods defined by Strict class inside the `xhtml' module. The + Strict class inside xhtml module is inherited inside this class so + all the methods there are also available here. Methods which + doesn't make a direct use of Strict methods are dependencies of + those which do make direct use of Strict methods. + + """ def __init__(self): """Initialize page data.""" - self.qs = cgi.parse() self.name = 'Home' self.title = 'The CentOS Project' self.description = 'Community Enterprise Operating System' @@ -157,7 +225,7 @@ class Layout(xhtml.Strict): # Define page header. This is the information displayed # between the page top and the page content. self.header = self.logo() - self.header += self.google() + self.header += self.google_ad() self.header += self.navibar() self.header += self.releases() self.header += self.page_links() @@ -191,32 +259,50 @@ class Layout(xhtml.Strict): return self.tag_div(attrs[0], [8,1], self.tag_a(attrs[1], [12,1], self.tag_img(attrs[2], [0,0]), 0), 1) - def google(self): - """Returns Google advertisements (468x60 pixels).""" - output = """ -
- Google Advertisement - - -
- -

- """ + def google_ad_example(self): + """Returns Google advertisement for offline testings.""" + + source = self.tag_img({'src':'/centos-web-pub/Images/ads-sample-468x60.png', 'alt':'Google Advertisement'}, [0,0]) + source = self.tag_a({'href':'', 'title':'Google Advertisement'}, [12,1], source ) + output = self.tag_div({'class':'google-ad'}, [8,1], source, 1) + output += self.separator({'class':'page-line'}, [8,1]) + + return output + + + def google_ad(self): + """Returns Google advertisement for online using.""" + + properties = {} + properties['google_ad_client'] = 'pub-6973128787810819' + properties['google_ad_width'] = '468' + properties['google_ad_height'] = '60' + properties['google_ad_format'] = '468x60_as' + properties['google_ad_type'] = 'text_image' + properties['google_ad_channel'] = '' + properties['google_color_border'] = '204c8d' + properties['google_color_bg'] = '345c97' + properties['google_color_link'] = '0000FF' + properties['google_color_text'] = 'FFFFFF' + properties['google_color_url'] = '008000' + + attrs = {} + attrs['type'] = "text/javascript" + + output = '\n' + + properties = self.tag_script(attrs, [12,1], output, 1) + + attrs['src'] = "http://pagead2.googlesyndication.com/pagead/show_ads.js" + + source = self.tag_script(attrs, [12,1], ' ', 0) + + output = self.tag_div({'class':'google-ad'}, [8,1], properties + source, 1) + output += self.separator({'class':'page-line'}, [8,1]) + return output @@ -278,7 +364,7 @@ class Layout(xhtml.Strict): return self.tag_div({'class': 'tabs'}, [8,1], navibar_tabs, 1) - def releases(self, names=['6.0'], attrs=[{'href': '/centos-web/p=releases&id=6.0'}]): + def releases(self): """Returns The CentOS Distribution last releases. This method introduces the `releases' method by providing @@ -296,7 +382,14 @@ class Layout(xhtml.Strict): """ releases = '' - title = self.tag_a({'href': '/centos-web/?p=releases'}, [0,0], 'Last Releases') + ':' + names = [] + names.append('6.0') + + attrs = [] + attrs.append({'href': qs_args({'p':'releases', 'id': 6.0})}) + + + title = self.tag_a({'href': qs_args({'p':'releases'})}, [0,0], 'Last Releases') + ':' title = self.tag_span({'class': 'title'}, [16,1], title) for i in range(len(names)): @@ -309,7 +402,7 @@ class Layout(xhtml.Strict): releases = self.tag_div({'class': 'left'}, [12,1], title + releases, 1) rsslink = self.tag_span('', [0,0], 'RSS') - rsslink = self.tag_a({'href': self.qs_args({'rss':'releases'}), 'title': 'RSS'}, [20,1], rsslink) + rsslink = self.tag_a({'href': qs_args({'rss':'releases'}), 'title': 'RSS'}, [20,1], rsslink) rsslink = self.tag_span({'class': 'rss'}, [16,1], rsslink, 1) rsslink = self.tag_div({'class': 'right'}, [12, 1], rsslink, 1) @@ -325,7 +418,7 @@ class Layout(xhtml.Strict): login. """ - last_visit = self.tag_a({'href': self.qs_args({'app':'', 'p':'logs'})}, [0,0], 'Logs') + last_visit = self.tag_a({'href': qs_args({'app':'', 'p':'logs'})}, [0,0], 'Logs') return self.tag_div({'class': 'logs'}, [12, 1], last_visit, 1) @@ -342,11 +435,11 @@ class Layout(xhtml.Strict): session = '' names.append('Lost your password?') - attrs.append({'href': self.qs_args({'app':'', 'p':'lostpwd'})}) + attrs.append({'href': qs_args({'app':'', 'p':'lostpwd'})}) names.append('Register') - attrs.append({'href': self.qs_args({'app':'', 'p':'register'})}) + attrs.append({'href': qs_args({'app':'', 'p':'register'})}) names.append('Login') - attrs.append({'href': self.qs_args({'app':'', 'p':'login'})}) + attrs.append({'href': qs_args({'app':'', 'p':'login'})}) for i in range(len(names)): output = self.tag_a(attrs[i], [20,1], str(names[i]), 0) @@ -452,66 +545,30 @@ class Layout(xhtml.Strict): metadata += self.tag_meta({'name': 'copyright', 'content': 'Copyright © ' + str(self.copyright)}, [4,0]) metadata += self.tag_title('', [4,1], self.title) metadata += self.tag_link({'href': '/centos-web-pub/stylesheet.css','rel': 'stylesheet', 'type': 'text/css'}, [4,0]) - metadata += self.tag_link({'href': '/centos-web-pub/Images/centos-fav.png', 'rel': 'shortcut icon', 'type': 'image/png'}, [4,1]) + metadata += self.tag_link({'href': '/centos-web-pub/centos-fav.png', 'rel': 'shortcut icon', 'type': 'image/png'}, [4,1]) return self.tag_head('', [0,1], metadata) - def qs_args(self, names={}): - """Returns query string arguments. - - The query string arguments are used to build links dynamically - and, this way, to create a browsable and logically organized - web environment. Such a construction generally needs to - retrive some of the values previously passed to the query - string and add new ones to it. - - names: A dictionary containing the variable name and value - pair used to build a new query string. - - When a variable is provied without a value, then its value is - retrived from the current query string. If a value isn't found - there neither, then the variable is removed from the new query - string. - - When a variable is provided with its value, then its value is - used to build the new query string. - - """ - output = '' - names_keys = names.keys() - names_keys.sort() - for key in names_keys: - if names[key] == '': - if key in self.qs: - names[key] = self.qs[key][0] - else: - continue - if output == '': - output = '?' - else: - output += '&' - output += key + '=' + str(names[key]) - - return '/centos-web/' + output - def searchform(self, size=20): + def searchform(self, size=15): """Returns search form. - The search form redirects the search up to the search page. Is - there, in the search page, where the search occurs. + The search form redirects user from the current page onto the + search page, where the keywords previously introduced in the + input field are processed then. - size: A number discribe how large the search text box is. + size: A number discribing how large the search box is. """ - input = self.tag_input({'type':'text', 'value':'', 'size':size}, [24,1]) + input = self.tag_input({'type':'text', 'value':'', 'size':size}, [0,0]) - action = self.tag_dt({}, [20,1], 'Search', 1) + action = self.tag_dt({}, [20,1], 'Search') action += self.tag_dd({}, [20,1], input) action = self.tag_dl({'class':'search'}, [16,1], action, 1) - return self.tag_form({'action': self.qs_args({'app':'', 'p':'search'}), + return self.tag_form({'action': qs_args({'app':'', 'p':'search'}), 'method':'post', 'title':'Search'}, [12,1], action, 1) @@ -520,68 +577,72 @@ class Layout(xhtml.Strict): update_date, category_id, comments, abstract): """Returns content resumen. - The content resumen is used to build the list of contents - output by `content_list()'. The content resumen pretends to be - concise and informative so the user can grab an idea what the - content is about. The content resumen is made of the following - information: + The content resumen is used to build the list of contents, + output by `content_list()' method. The content resumen intends + to be concise and informative so the user can grab a general + idea about the related content and what it is about. - attrs: A dictionary discribing the rows style. This is - useful to alternate the row background colors. + attrs: A dictionary discribing the rows style. This is useful + to alternate the row background colors. - id: A unique numerical value referring the content - identification. This is the value used on - administrative tasks like updating and deleting. + id: A unique numerical value referring the content + identification. This is the value used on administrative + tasks like updating and deleting. - title: A few words phrase describing the content, - up to 255 characters. + title: A few words phrase describing the content, up to 255 + characters. - author_id: A string referring the user email address, as - specified by RFC2822. The user email address is used - as id inside The CentOS User LDAP server, where user - specific information (e.g., surname, lastname, office, - phone, etc.) are stored in. This is the field that - bonds the user with the content he/she produces. + author_id: A string referring the user email address, as + specified by RFC2822. The user email address is used as id + inside The CentOS User LDAP server, where user specific + information (e.g., surname, lastname, office, phone, etc.) + are stored in. This is the field that bonds the user with + the content he/she produces. - commit_date: A string referring the timestamp the content - arrived to database for time. + commit_date: A string referring the timestamp the content + arrived to database for time. - update_date: A string representing the timestamp the - content was updated/revised for last time. + update_date: A string representing the timestamp the content + was updated/revised for last time. - category_id: A number refering the category id the - content is attached to. + category_id: A number refering the category id the content is + attached to. - abstract: One paragraphs describing the content. This - information is used to build the page metadata - information. When this value is not provided no - abstract information is displayed in the page, but the - is built using article's - first 255 characters. + abstract: One paragraphs describing the content. This + information is used to build the page metadata + information. When this value is not provided no abstract + information is displayed in the page, but the is built using article's first 255 + characters. - comments: A number representing how many comments the - content has received since it is in the database. + comments: A number representing how many comments the content + has received since it is in the database. The content itself is not displayed in the resumen, but in - `content_detailed()'. + `content_details()'. """ - title = self.tag_a({'href': self.qs_args({'app':'', 'p':'entry', 'id':id})}, [0,0], title) + title = self.tag_a({'href': qs_args({'app':'', 'p':'entry', 'id':id})}, [0,0], title) title = self.tag_h3({'class': 'title'}, [20,1], title, 0) - info = self.content_info(id, user_id, commit_date, update_date, category_id, comments, abstract) + info = self.content_info(id, user_id, commit_date, + update_date, category_id, comments, + abstract) return self.tag_div(attrs, [16,1], title + info, 1) def pagination(self): """Return content pagination.""" - previous = self.tag_a({'href':''}, [12,1], 'Previous') - previous = self.tag_span({'class':'previous'}, [12,1], previous, 1) - next = self.tag_a({'href':''}, [12,1], 'Next') - next = self.tag_span({'class':'next'}, [12,1], next, 1) - return self.tag_div({'class':'pagination'}, [12,1], previous + next + self.separator(), 1) + previous = self.tag_a({'href':''}, [0,0], 'Previous') + previous = self.tag_span({'class':'previous'}, [20,1], previous) + next = self.tag_a({'href':''}, [0,0], 'Next') + next = self.tag_span({'class':'next'}, [20,1], next) + separator = self.separator({'class':'page-line'}, [20,1]) + return self.tag_div({'class':'pagination'}, [16,1], previous + + next + separator, 1) - def content_info(self, content_id, user_id, commit_date, update_date, category_id, comments, abstract): + def content_info(self, content_id, user_id, commit_date, + update_date, category_id, comments, abstract): """Return content information. The content information provides a reduced view of content so @@ -603,7 +664,7 @@ class Layout(xhtml.Strict): category_id = 0 category_name = categories[category_id].capitalize() - category_name = self.tag_a({'href': self.qs_args({'app':'', 'p':'categories', 'id':category_id})}, [0,0], category_name) + category_name = self.tag_a({'href': qs_args({'app':'', 'p':'categories', 'id':category_id})}, [0,0], category_name) category_name = self.tag_span({'class':'category'}, [24,1], category_name) users = {} @@ -621,7 +682,7 @@ class Layout(xhtml.Strict): date = self.tag_span({'class':'date'}, [24,1], commit_date) - comments_attrs = {'href': self.qs_args({'app':'', 'p':'entry', 'id':content_id}) + '#comments'} + comments_attrs = {'href': qs_args({'app':'', 'p':'entry', 'id':content_id}) + '#comments'} if comments == 1: comments = self.tag_a(comments_attrs, [0,0], str(comments) + ' comment') elif comments > 1: @@ -682,7 +743,7 @@ class Layout(xhtml.Strict): list = output + self.pagination() + self.separator() list = self.tag_div({'id':'content-list'}, [12,1], list, 1) - actions = self.searchform(16) + self.categories() + self.archives() + actions = self.searchform() + self.categories() + self.archives() actions = self.tag_div({'id':'content-actions'}, [8,1], actions, 1) return actions + list @@ -726,8 +787,8 @@ class Layout(xhtml.Strict): This is the second paragraph of content.\n\ This is the third paragraph of content."]) - if 'id' in self.qs: - id = int(self.qs['id'][0]) + if 'id' in qs: + id = int(qs['id'][0]) title = rows[id][1] email = rows[id][2] commit_date = rows[id][3] @@ -759,14 +820,14 @@ class Layout(xhtml.Strict): """ categories = ['Unknown', 'Articles', 'Erratas', 'Events'] - dt = self.tag_dt({}, [12,1], 'Categories') + dt = self.tag_dt({}, [16,1], 'Categories') dd = '' for id in range(len(categories)): - category_attrs = {'href': self.qs_args({'app':'', 'p':'categories', 'id':id})} - a = self.tag_a(category_attrs, [16,0], categories[id] + ' (0)') - dd += self.tag_dd({}, [12,1], a, 1) + category_attrs = {'href': qs_args({'app':'', 'p':'categories', 'id':id})} + a = self.tag_a(category_attrs, [0,0], categories[id] + ' (0)') + dd += self.tag_dd({}, [16,1], a) - return self.tag_dl({},[8,1], dt + dd, 1) + return self.tag_dl({},[12,1], dt + dd, 1) def archives(self): @@ -775,21 +836,19 @@ class Layout(xhtml.Strict): archives['2011'] = ['January', 'February', 'March', 'April', 'May'] archives['2010'] = ['January', 'February'] - dt = self.tag_dt({}, [12,1], 'Archives') + dt = self.tag_dt({}, [16,1], 'Archives') year_dl = '' year_dd = '' for key in archives.keys(): - year_dt = self.tag_dt({},[12,1], key, 1) + year_dt = self.tag_dt({},[20,1], key) for id in range(len(archives[key])): - a = self.tag_a({'href': self.qs_args({'app':'', - 'p':'archives', 'year': key, 'month': id + 1})}, - [16,1], archives[key][id] + ' (0)') - year_dd += self.tag_dd({}, [12,1], a) - year_dl += self.tag_dl({'class':'year'}, [12,1], year_dt + year_dd, 1) + a = self.tag_a({'href': qs_args({'app':'', 'p':'archives', 'year': key, 'month': id + 1})}, [0,0], archives[key][id] + ' (0)') + year_dd += self.tag_dd({}, [20,1], a) + year_dl += self.tag_dl({'class':'year'}, [16,1], year_dt + year_dd, 1) year_dd = '' - return self.tag_dl({},[8,1], dt + year_dl, 1) + return self.tag_dl({},[12,1], dt + year_dl, 1) def page_top(self):