diff --git a/modules/bibformat/lib/elements/bfe_fulltext.py b/modules/bibformat/lib/elements/bfe_fulltext.py index 4d71b77e4..17bc841e2 100644 --- a/modules/bibformat/lib/elements/bfe_fulltext.py +++ b/modules/bibformat/lib/elements/bfe_fulltext.py @@ -1,287 +1,287 @@ # -*- coding: utf-8 -*- ## ## This file is part of Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 CERN. ## ## Invenio is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2 of the ## License, or (at your option) any later version. ## ## Invenio 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 ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """BibFormat element - Prints a links to fulltext """ __revision__ = "$Id$" import re from invenio.bibdocfile import BibRecDocs, file_strip_ext from invenio.messages import gettext_set_language from invenio.config import CFG_SITE_URL, CFG_CERN_SITE from cgi import escape from urlparse import urlparse from os.path import basename import urllib cern_arxiv_categories = ["astro-ph", "chao-dyn", "cond-mat", "gr-qc", "hep-ex", "hep-lat", "hep-ph", "hep-th", "math-ph", "math", "nucl-ex", "nucl-th", "out", "physics", "quant-ph", "q-alg", "cs", "adap-org", "comp-gas", "chem-ph", "cs", "math", "neuro-sys", "patt-sol", "solv-int", "acc-phys", "alg-geom", "ao-sci", "atom-ph", "cmp-lg", "dg-ga", "funct-an", "mtrl-th", "plasm-ph", "q-alg", "supr-con"] def format_element(bfo, style, separator='; ', show_icons='no', focus_on_main_file='no'): """ This is the default format for formatting fulltext links. When possible, it returns only the main file(s) (+ link to additional files if needed). If no distinction is made at submission time between main and additional files, returns all the files @param separator: the separator between urls. @param style: CSS class of the link @param show_icons: if 'yes', print icons for fulltexts @param focus_on_main_file: if 'yes' and a doctype 'Main' is found, prominently display this doctype. In that case other doctypes are - summarized with a link to the Fulltext tab, named "Additional files" + summarized with a link to the Files tab, named "Additional files" """ _ = gettext_set_language(bfo.lang) out = '' # Retrieve files (parsed_urls, old_versions, additionals) = get_files(bfo, \ distinguish_main_and_additional_files=focus_on_main_file.lower() == 'yes') main_urls = parsed_urls['main_urls'] others_urls = parsed_urls['others_urls'] if parsed_urls.has_key('cern_urls'): cern_urls = parsed_urls['cern_urls'] # Prepare style and icon if style != "": style = 'class="'+style+'"' if show_icons.lower() == 'yes': file_icon = '%s' % (CFG_SITE_URL, _("Download fulltext")) else: file_icon = '' # Build urls list. # Escape special chars for tag value. additional_str = '' if additionals: additional_str = ' (%s)' % _("additional files") versions_str = '' #if old_versions: #versions_str = ' (%s)' % _("older versions") if main_urls: last_name = "" main_urls_keys = sort_alphanumerically(main_urls.keys()) for descr in main_urls_keys: urls = main_urls[descr] if re.match(r'^\d+\s', descr) and urls[0][2] == 'png': # FIXME: we have probably hit a Plot (as link # description looks like '0001 This is Caption'), so # do not take it. This test is not ideal, we should # rather study doc type, and base ourselves on # Main/Additional/Plot etc. continue out += "%s: " % descr url_list = [] ## FIXME: This is so ugly! urls_dict = {} for url, name, format in urls: urls_dict[url] = (name, format) urls_dict_keys = sort_alphanumerically(urls_dict.keys()) for url in urls_dict_keys: name, format = urls_dict[url] if not name == last_name and len(main_urls) > 1: print_name = "%s - " % name else: print_name = "" last_name = name url_list.append(print_name + ''+ \ file_icon + format.upper()+'') out += separator.join(url_list) + additional_str + versions_str + '
' if CFG_CERN_SITE and cern_urls: link_word = len(cern_urls) == 1 and _('%(x_sitename)s link') or _('%(x_sitename)s links') out += '%s: ' % (link_word % {'x_sitename': 'CERN'}) url_list = [] for url, descr in cern_urls: url_list.append(''+ \ file_icon + escape(str(descr))+'') out += separator.join(url_list) if others_urls: external_link = len(others_urls) == 1 and _('external link') or _('external links') out += '%s: ' % external_link.capitalize() url_list = [] for url, descr in others_urls: url_list.append(''+ \ file_icon + escape(str(descr))+'') out += separator.join(url_list) + '
' if out.endswith('
'): out = out[:-len('
')] # When exported to text (eg. in WebAlert emails) we do not want to # display the link to the fulltext: if out: out = '' + out + '' return out def escape_values(bfo): """ Called by BibFormat in order to check if output of this element should be escaped. """ return 0 def get_files(bfo, distinguish_main_and_additional_files=True): """ Returns the files available for the given record. Returned structure is a tuple (parsed_urls, old_versions, additionals): - parsed_urls: contains categorized URLS (see details below) - old_versions: set to True if we can have access to old versions - additionals: set to True if we have other documents than the 'main' document 'parsed_urls' is a dictionary in the form: {'main_urls' : {'Main' : [('http://CFG_SITE_URL/record/1/files/aFile.pdf', 'aFile', 'PDF'), ('http://CFG_SITE_URL/record/1/files/aFile.gif', 'aFile', 'GIF')], 'Additional': [('http://CFG_SITE_URL/record/1/files/bFile.pdf', 'bFile', 'PDF')]}, 'other_urls': [('http://externalurl.com/aFile.pdf', 'Fulltext'), # url(8564_u), description(8564_z/y) ('http://externalurl.com/bFile.pdf', 'Fulltext')], 'cern_urls' : [('http://cern.ch/aFile.pdf', 'Fulltext'), # url(8564_u), description(8564_z/y) ('http://cern.ch/bFile.pdf', 'Fulltext')], } Some notes about returned structure: - key 'cern_urls' is only available on CERN site - keys in main_url dictionaries are defined by the BibDoc. - older versions are not part of the parsed urls - returns only main files when possible, that is when doctypes make a distinction between 'Main' files and other files. Otherwise returns all the files as main. This is only enabled if distinguish_main_and_additional_files is set to True """ _ = gettext_set_language(bfo.lang) urls = bfo.fields("8564_") bibarchive = BibRecDocs(bfo.recID) old_versions = False # We can provide link to older files. Will be # set to True if older files are found. additionals = False # We have additional files. Will be set to # True if additional files are found. # Prepare object to return parsed_urls = {'main_urls':{}, # Urls hosted by Invenio (bibdocs) 'others_urls':[] # External urls } if CFG_CERN_SITE: parsed_urls['cern_urls'] = [] # cern.ch urls # Doctypes can of any type, but when there is one file marked as # 'Main', we consider that there is a distinction between "main" # and "additional" files. Otherwise they will all be considered # equally as main files distinct_main_and_additional_files = False if len(bibarchive.list_bibdocs(doctype='Main')) > 0 and \ distinguish_main_and_additional_files: distinct_main_and_additional_files = True # Parse URLs for complete_url in urls: if complete_url.has_key('u'): url = complete_url['u'] (dummy, host, path, dummy, params, dummy) = urlparse(url) filename = urllib.unquote(basename(path)) name = file_strip_ext(filename) format = filename[len(name):] if format.startswith('.'): format = format[1:] descr = '' if complete_url.has_key('y'): descr = complete_url['y'] if not url.startswith(CFG_SITE_URL): # Not a bibdoc? if not descr: # For not bibdoc let's have a description # Display the URL in full: descr = url if CFG_CERN_SITE and 'cern.ch' in host and \ ('/setlink?' in url or \ 'cms' in host or \ 'documents.cern.ch' in url or \ 'doc.cern.ch' in url or \ 'preprints.cern.ch' in url): url_params_dict = dict([part.split('=') for part in params.split('&') \ if len(part) == 2]) if url_params_dict.has_key('categ') and \ (url_params_dict['categ'].split('.', 1)[0] in cern_arxiv_categories) and \ url_params_dict.has_key('id'): # Old arXiv links, used to be handled by # setlink. Provide direct links to arXiv for file_format, label in [('pdf', "PDF")]:#, #('ps', "PS"), #('e-print', "Source (generally TeX or LaTeX)"), #('abs', "Abstract")]: url = "http://arxiv.org/%(format)s/%(category)s/%(id)s" % \ {'format': file_format, 'category': url_params_dict['categ'], 'id': url_params_dict['id']} parsed_urls['others_urls'].append((url, "%s/%s %s" % \ (url_params_dict['categ'], url_params_dict['id'], label))) else: parsed_urls['others_urls'].append((url, descr)) # external url else: # It's a bibdoc! assigned = False for doc in bibarchive.list_bibdocs(): if int(doc.get_latest_version()) > 1: old_versions = True if True in [f.fullname.startswith(filename) \ for f in doc.list_all_files()]: assigned = True #doc.getIcon() if not doc.doctype == 'Main' and \ distinct_main_and_additional_files == True: # In that case we record that there are # additional files, but don't add them to # returned structure. additionals = True else: if not descr: descr = _('Fulltext') if not parsed_urls['main_urls'].has_key(descr): parsed_urls['main_urls'][descr] = [] parsed_urls['main_urls'][descr].append((url, name, format)) if not assigned: # Url is not a bibdoc :-S if not descr: descr = filename parsed_urls['others_urls'].append((url, descr)) # Let's put it in a general other url return (parsed_urls, old_versions, additionals) _RE_SPLIT = re.compile(r"\d+|\D+") def sort_alphanumerically(elements): elements = [([not token.isdigit() and token or int(token) for token in _RE_SPLIT.findall(element)], element) for element in elements] elements.sort() return [element[1] for element in elements] diff --git a/modules/bibformat/lib/elements/bfe_fulltext_mini.py b/modules/bibformat/lib/elements/bfe_fulltext_mini.py index 381d56cce..68e0c23c1 100644 --- a/modules/bibformat/lib/elements/bfe_fulltext_mini.py +++ b/modules/bibformat/lib/elements/bfe_fulltext_mini.py @@ -1,148 +1,148 @@ # -*- coding: utf-8 -*- ## ## This file is part of Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 CERN. ## ## Invenio is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2 of the ## License, or (at your option) any later version. ## ## Invenio 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 ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """BibFormat element - Prints a links to fulltext """ __revision__ = "$Id$" from invenio.bibformat_elements.bfe_fulltext import get_files, sort_alphanumerically from invenio.messages import gettext_set_language from invenio.config import CFG_SITE_URL, CFG_CERN_SITE from cgi import escape def format_element(bfo, style, separator='; ', show_icons='no', focus_on_main_file='yes'): """ This is the format for formatting fulltext links in the mini panel. @param separator: the separator between urls. @param style: CSS class of the link @param show_icons: if 'yes', print icons for fulltexts @param focus_on_main_file: if 'yes' and a doctype 'Main' is found, prominently display this doctype. In that case other doctypes are - summarized with a link to the Fulltext tab, named"Additional files". + summarized with a link to the Files tab, named"Additional files". """ _ = gettext_set_language(bfo.lang) out = '' # Retrieve files (parsed_urls, old_versions, additionals) = \ get_files(bfo, distinguish_main_and_additional_files=focus_on_main_file.lower() == 'yes') main_urls = parsed_urls['main_urls'] others_urls = parsed_urls['others_urls'] if parsed_urls.has_key('cern_urls'): cern_urls = parsed_urls['cern_urls'] # Prepare style if style != "": style = 'class="'+style+'"' # Build urls list. # Escape special chars for tag value. additional_str = '' if additionals: additional_str = separator + '(%s)' % _("additional files") versions_str = '' #if old_versions: #versions_str = separator + '(%s)' % _("older versions") if main_urls: # Put a big file icon if only one file if len(main_urls.keys()) == 1 and len(main_urls.items()[0][1]) == 1 and \ (not CFG_CERN_SITE or len(cern_urls) == 0) and len(others_urls) == 0 and \ show_icons.lower() == 'yes': file_icon = '%s
' % (CFG_SITE_URL, _("Download fulltext")) elif show_icons.lower() == 'yes': file_icon = '%s' % (CFG_SITE_URL, _("Download fulltext")) else: file_icon = '' last_name = "" main_urls_keys = sort_alphanumerically(main_urls.keys()) for descr in main_urls_keys: urls = main_urls[descr] out += '
%s: ' % descr url_list = [] ## FIXME: This is so ugly! urls_dict = {} for url, name, format in urls: urls_dict[url] = (name, format) urls_dict_keys = sort_alphanumerically(urls_dict.keys()) for url in urls_dict_keys: name, format = urls_dict[url] if not name == last_name and len(main_urls) > 1: print_name = "%s - " % name else: print_name = "" last_name = name url_list.append(print_name + ''+file_icon+format.upper()+'') out += separator + separator.join(url_list) + \ additional_str + versions_str + '
' if CFG_CERN_SITE and cern_urls: # Put a big file icon if only one file if len(main_urls.keys()) == 0 and \ len(cern_urls) == 1 and len(others_urls) == 0 and \ show_icons.lower() == 'yes': file_icon = '%s
' % (CFG_SITE_URL, _("Download fulltext")) elif show_icons.lower() == 'yes': file_icon = '%s' % (CFG_SITE_URL, _("Download fulltext")) else: file_icon = '' link_word = len(cern_urls) == 1 and _('%(x_sitename)s link') or _('%(x_sitename)s links') out += '%s:
' % (link_word % {'x_sitename': 'CERN'}) url_list = [] for url, descr in cern_urls: url_list.append(''+file_icon+escape(str(descr))+'') out += '' + separator.join(url_list) + '' out += "
" if others_urls: # Put a big file icon if only one file if len(main_urls.keys()) == 0 and \ (not CFG_CERN_SITE or len(cern_urls) == 0) and len(others_urls) == 1 and \ show_icons.lower() == 'yes': file_icon = '%s
' % (CFG_SITE_URL, _("Download fulltext")) elif show_icons.lower() == 'yes': file_icon = '%s' % (CFG_SITE_URL, _("Download fulltext")) else: file_icon = '' external_link = len(others_urls) == 1 and _('external link') or _('external links') out += '%s:%s' % (external_link, separator) url_list = [] for url, descr in others_urls: # we don't need to show the plot links here, and all are pngs. if url.find('.png') > -1: continue url_list.append(''+file_icon+escape(str(descr))+'') out += '' + separator.join(url_list) + '' if out.endswith('
'): out = out[:-len('
')] return out def escape_values(bfo): """ Called by BibFormat in order to check if output of this element should be escaped. """ return 0 diff --git a/modules/websearch/lib/websearchadminlib.py b/modules/websearch/lib/websearchadminlib.py index 05159268e..7b52678ae 100644 --- a/modules/websearch/lib/websearchadminlib.py +++ b/modules/websearch/lib/websearchadminlib.py @@ -1,3450 +1,3450 @@ ## This file is part of Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 CERN. ## ## Invenio is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2 of the ## License, or (at your option) any later version. ## ## Invenio 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 ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. # pylint: disable=C0301 """Invenio WebSearch Administrator Interface.""" __revision__ = "$Id$" import cgi import random import time import sys if sys.hexversion < 0x2040000: # pylint: disable=W0622 from sets import Set as set # pylint: enable=W0622 from invenio.config import \ CFG_CACHEDIR, \ CFG_SITE_LANG, \ CFG_SITE_NAME, \ CFG_SITE_URL,\ CFG_WEBCOMMENT_ALLOW_COMMENTS,\ CFG_WEBCOMMENT_ALLOW_REVIEWS,\ CFG_INSPIRE_SITE from invenio.bibrankadminlib import \ write_outcome, \ modify_translations, \ get_def_name, \ get_name, \ get_languages, \ addadminbox, \ tupletotable, \ createhiddenform from invenio.dbquery import \ run_sql, \ get_table_update_time from invenio.websearch_external_collections import \ external_collections_dictionary, \ external_collection_sort_engine_by_name, \ external_collection_get_state, \ external_collection_get_update_state_list, \ external_collection_apply_changes from invenio.websearch_external_collections_utils import \ get_collection_descendants from invenio.websearch_external_collections_config import CFG_EXTERNAL_COLLECTION_STATES_NAME #from invenio.bibformat_elements import bfe_references #from invenio.bibformat_engine import BibFormatObject from invenio.bibdocfile import BibRecDocs from invenio.messages import gettext_set_language #from invenio.bibrank_citation_searcher import get_cited_by from invenio.access_control_admin import acc_get_action_id from invenio.access_control_config import VIEWRESTRCOLL from invenio.errorlib import register_exception def getnavtrail(previous = ''): """Get the navtrail""" navtrail = """Admin Area """ % (CFG_SITE_URL,) navtrail = navtrail + previous return navtrail def perform_modifytranslations(colID, ln, sel_type='', trans=[], confirm=-1, callback='yes'): """Modify the translations of a collection sel_type - the nametype to modify trans - the translations in the same order as the languages from get_languages()""" output = '' subtitle = '' sitelangs = get_languages() if confirm in ["2", 2] and colID: finresult = modify_translations(colID, sitelangs, sel_type, trans, "collection") col_dict = dict(get_def_name('', "collection")) if colID and col_dict.has_key(int(colID)): colID = int(colID) subtitle = """3. Modify translations for collection '%s'   [?]""" % (col_dict[colID], CFG_SITE_URL) if type(trans) is str: trans = [trans] if sel_type == '': sel_type = get_col_nametypes()[0][0] header = ['Language', 'Translation'] actions = [] types = get_col_nametypes() if len(types) > 1: text = """ Name type """ output += createhiddenform(action="modifytranslations#3", text=text, button="Select", colID=colID, ln=ln, confirm=0) if confirm in [-1, "-1", 0, "0"]: trans = [] for (key, value) in sitelangs: try: trans_names = get_name(colID, key, sel_type, "collection") trans.append(trans_names[0][0]) except StandardError, e: trans.append('') for nr in range(0, len(sitelangs)): actions.append(["%s %s" % (sitelangs[nr][1], (sitelangs[nr][0]==CFG_SITE_LANG and '(def)' or ''))]) actions[-1].append('' % trans[nr]) text = tupletotable(header=header, tuple=actions) output += createhiddenform(action="modifytranslations#3", text=text, button="Modify", colID=colID, sel_type=sel_type, ln=ln, confirm=2) if sel_type and len(trans) and confirm in ["2", 2]: output += write_outcome(finresult) body = [output] if callback: return perform_editcollection(colID, ln, "perform_modifytranslations", addadminbox(subtitle, body)) else: return addadminbox(subtitle, body) def perform_modifyrankmethods(colID, ln, func='', rnkID='', confirm=0, callback='yes'): """Modify which rank methods is visible to the collection func - remove or add rank method rnkID - the id of the rank method.""" output = "" subtitle = "" col_dict = dict(get_def_name('', "collection")) rnk_dict = dict(get_def_name('', "rnkMETHOD")) if colID and col_dict.has_key(int(colID)): colID = int(colID) if func in ["0", 0] and confirm in ["1", 1]: finresult = attach_rnk_col(colID, rnkID) elif func in ["1", 1] and confirm in ["1", 1]: finresult = detach_rnk_col(colID, rnkID) subtitle = """9. Modify rank options for collection '%s'   [?]""" % (col_dict[colID], CFG_SITE_URL) output = """
The rank methods enabled for the collection '%s' is:
""" % col_dict[colID] rnkmethods = get_col_rnk(colID, ln) output += """
""" if not rnkmethods: output += """No rank methods""" else: for id, name in rnkmethods: output += """%s, """ % name output += """
""" rnk_list = get_def_name('', "rnkMETHOD") rnk_dict_in_col = dict(get_col_rnk(colID, ln)) rnk_list = filter(lambda x: not rnk_dict_in_col.has_key(x[0]), rnk_list) if rnk_list: text = """ Enable: """ output += createhiddenform(action="modifyrankmethods#9", text=text, button="Enable", colID=colID, ln=ln, func=0, confirm=1) if confirm in ["1", 1] and func in ["0", 0] and int(rnkID) != -1: output += write_outcome(finresult) elif confirm not in ["0", 0] and func in ["0", 0]: output += """Please select a rank method.""" coll_list = get_col_rnk(colID, ln) if coll_list: text = """ Disable: """ output += createhiddenform(action="modifyrankmethods#9", text=text, button="Disable", colID=colID, ln=ln, func=1, confirm=1) if confirm in ["1", 1] and func in ["1", 1] and int(rnkID) != -1: output += write_outcome(finresult) elif confirm not in ["0", 0] and func in ["1", 1]: output += """Please select a rank method.""" body = [output] if callback: return perform_editcollection(colID, ln, "perform_modifyrankmethods", addadminbox(subtitle, body)) else: return addadminbox(subtitle, body) def perform_addcollectiontotree(colID, ln, add_dad='', add_son='', rtype='', mtype='', callback='yes', confirm=-1): """Form to add a collection to the tree. add_dad - the dad to add the collection to add_son - the collection to add rtype - add it as a regular or virtual mtype - add it to the regular or virtual tree.""" output = "" output2 = "" subtitle = """Attach collection to tree   [?]""" % (CFG_SITE_URL) col_dict = dict(get_def_name('', "collection")) if confirm not in [-1, "-1"] and not (add_son and add_dad and rtype): output2 += """All fields must be filled.

""" elif add_son and add_dad and rtype: add_son = int(add_son) add_dad = int(add_dad) if confirm not in [-1, "-1"]: if add_son == add_dad: output2 += """Cannot add a collection as a pointer to itself.

""" elif check_col(add_dad, add_son): res = add_col_dad_son(add_dad, add_son, rtype) output2 += write_outcome(res) if res[0] == 1: output2 += """
The collection will appear on your website after the next webcoll run. You can either run it manually or wait until bibsched does it for you.


""" else: output2 += """Cannot add the collection '%s' as a %s subcollection of '%s' since it will either create a loop, or the association already exists.

""" % (col_dict[add_son], (rtype=="r" and 'regular' or 'virtual'), col_dict[add_dad]) add_son = '' add_dad = '' rtype = '' tree = get_col_tree(colID) col_list = col_dict.items() col_list.sort(compare_on_val) output = show_coll_not_in_tree(colID, ln, col_dict) text = """ Attach collection:
to parent collection:
""" text += """ with relationship: """ % ((rtype=="r" and 'selected="selected"' or ''), (rtype=="v" and 'selected="selected"' or '')) output += createhiddenform(action="%s/admin/websearch/websearchadmin.py/addcollectiontotree" % CFG_SITE_URL, text=text, button="Add", colID=colID, ln=ln, confirm=1) output += output2 #output += perform_showtree(colID, ln) body = [output] if callback: return perform_index(colID, ln, mtype="perform_addcollectiontotree", content=addadminbox(subtitle, body)) else: return addadminbox(subtitle, body) def perform_addcollection(colID, ln, colNAME='', dbquery='', callback="yes", confirm=-1): """form to add a new collection. colNAME - the name of the new collection dbquery - the dbquery of the new collection""" output = "" subtitle = """Create new collection   [?]""" % (CFG_SITE_URL) text = """ Default name
""" % colNAME output = createhiddenform(action="%s/admin/websearch/websearchadmin.py/addcollection" % CFG_SITE_URL, text=text, colID=colID, ln=ln, button="Add collection", confirm=1) if colNAME and confirm in ["1", 1]: res = add_col(colNAME, '') output += write_outcome(res) if res[0] == 1: output += perform_addcollectiontotree(colID=colID, ln=ln, add_son=res[1], callback='') elif confirm not in ["-1", -1]: output += """Please give the collection a name.""" body = [output] if callback: return perform_index(colID, ln=ln, mtype="perform_addcollection", content=addadminbox(subtitle, body)) else: return addadminbox(subtitle, body) def perform_modifydbquery(colID, ln, dbquery='', callback='yes', confirm=-1): """form to modify the dbquery of the collection. dbquery - the dbquery of the collection.""" subtitle = '' output = "" col_dict = dict(get_def_name('', "collection")) if colID and col_dict.has_key(int(colID)): colID = int(colID) subtitle = """1. Modify collection query for collection '%s'   [?]""" % (col_dict[colID], CFG_SITE_URL) if confirm == -1: res = run_sql("SELECT dbquery FROM collection WHERE id=%s" % colID) dbquery = res[0][0] if not dbquery: dbquery = '' reg_sons = len(get_col_tree(colID, 'r')) vir_sons = len(get_col_tree(colID, 'v')) if reg_sons > 1: if dbquery: output += "Warning: This collection got subcollections, and should because of this not have a collection query, for further explanation, check the WebSearch Guide
" elif reg_sons <= 1: if not dbquery: output += "Warning: This collection does not have any subcollections, and should because of this have a collection query, for further explanation, check the WebSearch Guide
" text = """ Query
""" % cgi.escape(dbquery, 1) output += createhiddenform(action="modifydbquery", text=text, button="Modify", colID=colID, ln=ln, confirm=1) if confirm in ["1", 1]: res = modify_dbquery(colID, dbquery) if res: if dbquery == "": text = """Query removed for this collection.""" else: text = """Query set for this collection.""" else: text = """Sorry, could not change query.""" output += text body = [output] if callback: return perform_editcollection(colID, ln, "perform_modifydbquery", addadminbox(subtitle, body)) else: return addadminbox(subtitle, body) def perform_modifycollectiontree(colID, ln, move_up='', move_down='', move_from='', move_to='', delete='', rtype='', callback='yes', confirm=0): """to modify the collection tree: move a collection up and down, delete a collection, or change the father of the collection. colID - the main collection of the tree, the root move_up - move this collection up (is not the collection id, but the place in the tree) move_up - move this collection down (is not the collection id, but the place in the tree) move_from - move this collection from the current positon (is not the collection id, but the place in the tree) move_to - move the move_from collection and set this as it's father. (is not the collection id, but the place in the tree) delete - delete this collection from the tree (is not the collection id, but the place in the tree) rtype - the type of the collection in the tree, regular or virtual""" colID = int(colID) tree = get_col_tree(colID, rtype) col_dict = dict(get_def_name('', "collection")) subtitle = """Modify collection tree: %s   [?]   Printer friendly version""" % (col_dict[colID], CFG_SITE_URL, CFG_SITE_URL, colID, ln) fin_output = "" output = "" try: if move_up: move_up = int(move_up) switch = find_last(tree, move_up) if switch and switch_col_treescore(tree[move_up], tree[switch]): output += """Moved the %s collection '%s' up and '%s' down.

""" % ((rtype=="r" and 'regular' or 'virtual'), col_dict[tree[move_up][0]], col_dict[tree[switch][0]]) else: output += """Could not move the %s collection '%s' up and '%s' down.

""" % ((rtype=="r" and 'regular' or 'virtual'), col_dict[tree[move_up][0]], col_dict[tree[switch][0]]) elif move_down: move_down = int(move_down) switch = find_next(tree, move_down) if switch and switch_col_treescore(tree[move_down], tree[switch]): output += """Moved the %s collection '%s' down and '%s' up.

""" % ((rtype=="r" and 'regular' or 'virtual'), col_dict[tree[move_down][0]], col_dict[tree[switch][0]]) else: output += """Could not move the %s collection '%s' up and '%s' down.

""" % ((rtype=="r" and 'regular' or 'virtual'), col_dict[tree[move_up][0]],col_dict[tree[switch][0]]) elif delete: delete = int(delete) if confirm in [0, "0"]: if col_dict[tree[delete][0]] != col_dict[tree[delete][3]]: text = """Do you want to remove the %s collection '%s' and its subcollections in the %s collection '%s'. """ % ((tree[delete][4]=="r" and 'regular' or 'virtual'), col_dict[tree[delete][0]], (rtype=="r" and 'regular' or 'virtual'), col_dict[tree[delete][3]]) else: text = """Do you want to remove all subcollections of the %s collection '%s'. """ % ((rtype=="r" and 'regular' or 'virtual'), col_dict[tree[delete][3]]) output += createhiddenform(action="%s/admin/websearch/websearchadmin.py/modifycollectiontree#tree" % CFG_SITE_URL, text=text, button="Confirm", colID=colID, delete=delete, rtype=rtype, ln=ln, confirm=1) output += createhiddenform(action="%s/admin/websearch/websearchadmin.py/index?mtype=perform_modifycollectiontree#tree" % CFG_SITE_URL, text="To cancel", button="Cancel", colID=colID, ln=ln) else: if remove_col_subcol(tree[delete][0], tree[delete][3], rtype): if col_dict[tree[delete][0]] != col_dict[tree[delete][3]]: output += """Removed the %s collection '%s' and its subcollections in subdirectory '%s'.

""" % ((tree[delete][4]=="r" and 'regular' or 'virtual'), col_dict[tree[delete][0]], col_dict[tree[delete][3]]) else: output += """Removed the subcollections of the %s collection '%s'.

""" % ((rtype=="r" and 'regular' or 'virtual'), col_dict[tree[delete][3]]) else: output += """Could not remove the collection from the tree.

""" delete = '' elif move_from and not move_to: move_from_rtype = move_from[0] move_from_id = int(move_from[1:len(move_from)]) text = """Select collection to place the %s collection '%s' under.

""" % ((move_from_rtype=="r" and 'regular' or 'virtual'), col_dict[tree[move_from_id][0]]) output += createhiddenform(action="%s/admin/websearch/websearchadmin.py/index?mtype=perform_modifycollectiontree#tree" % CFG_SITE_URL, text=text, button="Cancel", colID=colID, ln=ln) elif move_from and move_to: move_from_rtype = move_from[0] move_from_id = int(move_from[1:len(move_from)]) move_to_rtype = move_to[0] move_to_id = int(move_to[1:len(move_to)]) tree_from = get_col_tree(colID, move_from_rtype) tree_to = get_col_tree(colID, move_to_rtype) if confirm in [0, '0']: if move_from_id == move_to_id and move_from_rtype == move_to_rtype: output += """Cannot move to itself.

""" elif tree_from[move_from_id][3] == tree_to[move_to_id][0] and move_from_rtype==move_to_rtype: output += """The collection is already there.

""" elif check_col(tree_to[move_to_id][0], tree_from[move_from_id][0]) or (tree_to[move_to_id][0] == 1 and tree_from[move_from_id][3] == tree_to[move_to_id][0] and move_from_rtype != move_to_rtype): text = """Move %s collection '%s' to the %s collection '%s'. """ % ((tree_from[move_from_id][4]=="r" and 'regular' or 'virtual'), col_dict[tree_from[move_from_id][0]], (tree_to[move_to_id][4]=="r" and 'regular' or 'virtual'), col_dict[tree_to[move_to_id][0]]) output += createhiddenform(action="%s/admin/websearch/websearchadmin.py/modifycollectiontree#tree" % CFG_SITE_URL, text=text, button="Confirm", colID=colID, move_from=move_from, move_to=move_to, ln=ln, rtype=rtype, confirm=1) output += createhiddenform(action="%s/admin/websearch/websearchadmin.py/index?mtype=perform_modifycollectiontree#tree" % CFG_SITE_URL, text="""To cancel""", button="Cancel", colID=colID, ln=ln) else: output += """Cannot move the collection '%s' and set it as a subcollection of '%s' since it will create a loop.

""" % (col_dict[tree_from[move_from_id][0]], col_dict[tree_to[move_to_id][0]]) else: if (move_to_id != 0 and move_col_tree(tree_from[move_from_id], tree_to[move_to_id])) or (move_to_id == 0 and move_col_tree(tree_from[move_from_id], tree_to[move_to_id], move_to_rtype)): output += """Moved %s collection '%s' to the %s collection '%s'.

""" % ((move_from_rtype=="r" and 'regular' or 'virtual'), col_dict[tree_from[move_from_id][0]], (move_to_rtype=="r" and 'regular' or 'virtual'), col_dict[tree_to[move_to_id][0]]) else: output += """Could not move %s collection '%s' to the %s collection '%s'.

""" % ((move_from_rtype=="r" and 'regular' or 'virtual'), col_dict[tree_from[move_from_id][0]], (move_to_rtype=="r" and 'regular' or 'virtual'), col_dict[tree_to[move_to_id][0]]) move_from = '' move_to = '' else: output += """ """ except StandardError, e: register_exception() return """An error occured. """ output += """
Narrow by collection: Focus on...:
""" tree = get_col_tree(colID, 'r') output += create_colltree(tree, col_dict, colID, ln, move_from, move_to, 'r', "yes") output += """ """ tree = get_col_tree(colID, 'v') output += create_colltree(tree, col_dict, colID, ln, move_from, move_to, 'v', "yes") output += """
""" body = [output] if callback: return perform_index(colID, ln, mtype="perform_modifycollectiontree", content=addadminbox(subtitle, body)) else: return addadminbox(subtitle, body) def perform_showtree(colID, ln): """create collection tree/hiarchy""" col_dict = dict(get_def_name('', "collection")) subtitle = "Collection tree: %s" % col_dict[int(colID)] output = """
Narrow by collection: Focus on...:
""" tree = get_col_tree(colID, 'r') output += create_colltree(tree, col_dict, colID, ln, '', '', 'r', '') output += """ """ tree = get_col_tree(colID, 'v') output += create_colltree(tree, col_dict, colID, ln, '', '', 'v', '') output += """
""" body = [output] return addadminbox(subtitle, body) def perform_addportalbox(colID, ln, title='', body='', callback='yes', confirm=-1): """form to add a new portalbox title - the title of the portalbox body - the body of the portalbox""" col_dict = dict(get_def_name('', "collection")) colID = int(colID) subtitle = """Create new portalbox""" text = """ Title
Body
""" % (cgi.escape(title), cgi.escape(body)) output = createhiddenform(action="addportalbox#5.1", text=text, button="Add", colID=colID, ln=ln, confirm=1) if body and confirm in [1, "1"]: res = add_pbx(title, body) output += write_outcome(res) if res[1] == 1: output += """Add portalbox to collection""" % (colID, ln, res[1]) elif confirm not in [-1, "-1"]: output += """Body field must be filled. """ body = [output] return perform_showportalboxes(colID, ln, content=addadminbox(subtitle, body)) def perform_addexistingportalbox(colID, ln, pbxID=-1, score=0, position='', sel_ln='', callback='yes', confirm=-1): """form to add an existing portalbox to a collection. colID - the collection to add the portalbox to pbxID - the portalbox to add score - the importance of the portalbox. position - the position of the portalbox on the page sel_ln - the language of the portalbox""" subtitle = """Add existing portalbox to collection""" output = "" colID = int(colID) res = get_pbx() pos = get_pbx_pos() lang = dict(get_languages()) col_dict = dict(get_def_name('', "collection")) pbx_dict = dict(map(lambda x: (x[0], x[1]), res)) col_pbx = get_col_pbx(colID) col_pbx = dict(map(lambda x: (x[0], x[5]), col_pbx)) if len(res) > 0: text = """ Portalbox
Language
Position " output += createhiddenform(action="addexistingportalbox#5.2", text=text, button="Add", colID=colID, ln=ln, confirm=1) else: output = """No existing portalboxes to add, please create a new one. """ if pbxID > -1 and position and sel_ln and confirm in [1, "1"]: pbxID = int(pbxID) res = add_col_pbx(colID, pbxID, sel_ln, position, '') output += write_outcome(res) elif pbxID > -1 and confirm not in [-1, "-1"]: output += """All fields must be filled. """ body = [output] output = "
" + addadminbox(subtitle, body) return perform_showportalboxes(colID, ln, content=output) def perform_deleteportalbox(colID, ln, pbxID=-1, callback='yes', confirm=-1): """form to delete a portalbox which is not in use. colID - the current collection. pbxID - the id of the portalbox""" subtitle = """Delete an unused portalbox""" output = "" colID = int(colID) if pbxID not in [-1, "-1"] and confirm in [1, "1"]: ares = get_pbx() pbx_dict = dict(map(lambda x: (x[0], x[1]), ares)) if pbx_dict.has_key(int(pbxID)): pname = pbx_dict[int(pbxID)] ares = delete_pbx(int(pbxID)) else: return """This portalbox does not exist""" res = get_pbx() col_dict = dict(get_def_name('', "collection")) pbx_dict = dict(map(lambda x: (x[0], x[1]), res)) col_pbx = get_col_pbx() col_pbx = dict(map(lambda x: (x[0], x[5]), col_pbx)) if len(res) > 0: text = """ Portalbox
""" output += createhiddenform(action="deleteportalbox#5.3", text=text, button="Delete", colID=colID, ln=ln, confirm=1) if pbxID not in [-1, "-1"]: pbxID = int(pbxID) if confirm in [1, "1"]: output += write_outcome(ares) elif confirm not in [-1, "-1"]: output += """Choose a portalbox to delete. """ body = [output] output = "
" + addadminbox(subtitle, body) return perform_showportalboxes(colID, ln, content=output) def perform_modifyportalbox(colID, ln, pbxID=-1, score='', position='', sel_ln='', title='', body='', callback='yes', confirm=-1): """form to modify a portalbox in a collection, or change the portalbox itself. colID - the id of the collection. pbxID - the portalbox to change score - the score of the portalbox connected to colID which should be changed. position - the position of the portalbox in collection colID to change.""" subtitle = "" output = "" colID = int(colID) res = get_pbx() pos = get_pbx_pos() lang = dict(get_languages()) col_dict = dict(get_def_name('', "collection")) pbx_dict = dict(map(lambda x: (x[0], x[1]), res)) col_pbx = get_col_pbx(colID) col_pbx = dict(map(lambda x: (x[0], x[5]), col_pbx)) if pbxID not in [-1, "-1"]: pbxID = int(pbxID) subtitle = """Modify portalbox '%s' for this collection""" % pbx_dict[pbxID] col_pbx = get_col_pbx(colID) if not (score and position) and not (body and title): for (id_pbx, id_collection, tln, score, position, title, body) in col_pbx: if id_pbx == pbxID: break output += """Collection (presentation) specific values (Changes implies only to this collection.)
""" text = """ Position
""" output += createhiddenform(action="modifyportalbox#5.4", text=text, button="Modify", colID=colID, pbxID=pbxID, score=score, title=title, body=cgi.escape(body, 1), sel_ln=sel_ln, ln=ln, confirm=3) if pbxID > -1 and score and position and confirm in [3, "3"]: pbxID = int(pbxID) res = modify_pbx(colID, pbxID, sel_ln, score, position, '', '') res2 = get_pbx() pbx_dict = dict(map(lambda x: (x[0], x[1]), res2)) output += write_outcome(res) output += """
Portalbox (content) specific values (any changes appears everywhere the portalbox is used.)""" text = """ Title
""" % cgi.escape(title) text += """ Body
""" % cgi.escape(body) output += createhiddenform(action="modifyportalbox#5.4", text=text, button="Modify", colID=colID, pbxID=pbxID, sel_ln=sel_ln, score=score, position=position, ln=ln, confirm=4) if pbxID > -1 and confirm in [4, "4"]: pbxID = int(pbxID) res = modify_pbx(colID, pbxID, sel_ln, '', '', title, body) output += write_outcome(res) else: output = """No portalbox to modify.""" body = [output] output = "
" + addadminbox(subtitle, body) return perform_showportalboxes(colID, ln, content=output) def perform_switchpbxscore(colID, id_1, id_2, sel_ln, ln): """Switch the score of id_1 and id_2 in collection_portalbox. colID - the current collection id_1/id_2 - the id's to change the score for. sel_ln - the language of the portalbox""" output = "" res = get_pbx() pbx_dict = dict(map(lambda x: (x[0], x[1]), res)) res = switch_pbx_score(colID, id_1, id_2, sel_ln) output += write_outcome(res) return perform_showportalboxes(colID, ln, content=output) def perform_showportalboxes(colID, ln, callback='yes', content='', confirm=-1): """show the portalboxes of this collection. colID - the portalboxes to show the collection for.""" colID = int(colID) col_dict = dict(get_def_name('', "collection")) subtitle = """5. Modify portalboxes for collection '%s'   [?]""" % (col_dict[colID], CFG_SITE_URL) output = "" pos = get_pbx_pos() output = """
Portalbox actions (not related to this collection)
Create new portalbox
Delete an unused portalbox
Collection specific actions
Add existing portalbox to collection
""" % (colID, ln, colID, ln, colID, ln) header = ['Position', 'Language', '', 'Title', 'Actions'] actions = [] sitelangs = get_languages() lang = dict(sitelangs) pos_list = pos.items() pos_list.sort() if len(get_col_pbx(colID)) > 0: for (key, value) in sitelangs: for (pos_key, pos_value) in pos_list: res = get_col_pbx(colID, key, pos_key) i = 0 for (pbxID, colID_pbx, tln, score, position, title, body) in res: move = """
""" if i != 0: move += """up""" % (CFG_SITE_URL, colID, ln, pbxID, res[i - 1][0], tln, random.randint(0, 1000), CFG_SITE_URL) else: move += "   " move += "" i += 1 if i != len(res): move += """down""" % (CFG_SITE_URL, colID, ln, pbxID, res[i][0], tln, random.randint(0, 1000), CFG_SITE_URL) move += """
""" actions.append(["%s" % (i==1 and pos[position] or ''), "%s" % (i==1 and lang[tln] or ''), move, "%s" % title]) for col in [(('Modify', 'modifyportalbox'), ('Remove', 'removeportalbox'),)]: actions[-1].append('%s' % (CFG_SITE_URL, col[0][1], colID, ln, pbxID, tln, col[0][0])) for (str, function) in col[1:]: actions[-1][-1] += ' / %s' % (CFG_SITE_URL, function, colID, ln, pbxID, tln, str) output += tupletotable(header=header, tuple=actions) else: output += """No portalboxes exists for this collection""" output += content body = [output] if callback: return perform_editcollection(colID, ln, "perform_showportalboxes", addadminbox(subtitle, body)) else: return addadminbox(subtitle, body) def perform_removeportalbox(colID, ln, pbxID='', sel_ln='', callback='yes', confirm=0): """form to remove a portalbox from a collection. colID - the current collection, remove the portalbox from this collection. sel_ln - remove the portalbox with this language pbxID - remove the portalbox with this id""" subtitle = """Remove portalbox""" output = "" col_dict = dict(get_def_name('', "collection")) res = get_pbx() pbx_dict = dict(map(lambda x: (x[0], x[1]), res)) if colID and pbxID and sel_ln: colID = int(colID) pbxID = int(pbxID) if confirm in ["0", 0]: text = """Do you want to remove the portalbox '%s' from the collection '%s'.""" % (pbx_dict[pbxID], col_dict[colID]) output += createhiddenform(action="removeportalbox#5.5", text=text, button="Confirm", colID=colID, pbxID=pbxID, sel_ln=sel_ln, confirm=1) elif confirm in ["1", 1]: res = remove_pbx(colID, pbxID, sel_ln) output += write_outcome(res) body = [output] output = "
" + addadminbox(subtitle, body) return perform_showportalboxes(colID, ln, content=output) def perform_switchfmtscore(colID, type, id_1, id_2, ln): """Switch the score of id_1 and id_2 in the table type. colID - the current collection id_1/id_2 - the id's to change the score for. type - like "format" """ fmt_dict = dict(get_def_name('', "format")) res = switch_score(colID, id_1, id_2, type) output = write_outcome(res) return perform_showoutputformats(colID, ln, content=output) def perform_switchfldscore(colID, id_1, id_2, fmeth, ln): """Switch the score of id_1 and id_2 in collection_field_fieldvalue. colID - the current collection id_1/id_2 - the id's to change the score for.""" fld_dict = dict(get_def_name('', "field")) res = switch_fld_score(colID, id_1, id_2) output = write_outcome(res) if fmeth == "soo": return perform_showsortoptions(colID, ln, content=output) elif fmeth == "sew": return perform_showsearchfields(colID, ln, content=output) elif fmeth == "seo": return perform_showsearchoptions(colID, ln, content=output) def perform_switchfldvaluescore(colID, id_1, id_fldvalue_1, id_fldvalue_2, ln): """Switch the score of id_1 and id_2 in collection_field_fieldvalue. colID - the current collection id_1/id_2 - the id's to change the score for.""" name_1 = run_sql("SELECT name from fieldvalue where id=%s", (id_fldvalue_1, ))[0][0] name_2 = run_sql("SELECT name from fieldvalue where id=%s", (id_fldvalue_2, ))[0][0] res = switch_fld_value_score(colID, id_1, id_fldvalue_1, id_fldvalue_2) output = write_outcome(res) return perform_modifyfield(colID, fldID=id_1, ln=ln, content=output) def perform_addnewfieldvalue(colID, fldID, ln, name='', value='', callback="yes", confirm=-1): """form to add a new fieldvalue. name - the name of the new fieldvalue value - the value of the new fieldvalue """ output = "" subtitle = """Add new value""" text = """ Display name
Search value
""" % (name, value) output = createhiddenform(action="%s/admin/websearch/websearchadmin.py/addnewfieldvalue" % CFG_SITE_URL, text=text, colID=colID, fldID=fldID, ln=ln, button="Add", confirm=1) if name and value and confirm in ["1", 1]: res = add_fldv(name, value) output += write_outcome(res) if res[0] == 1: res = add_col_fld(colID, fldID, 'seo', res[1]) if res[0] == 0: output += "
" + write_outcome(res) elif confirm not in ["-1", -1]: output += """Please fill in name and value. """ body = [output] output = "
" + addadminbox(subtitle, body) return perform_modifyfield(colID, fldID=fldID, ln=ln, content=output) def perform_modifyfieldvalue(colID, fldID, fldvID, ln, name='', value='', callback="yes", confirm=-1): """form to modify a fieldvalue. name - the name of the fieldvalue value - the value of the fieldvalue """ if confirm in [-1, "-1"]: res = get_fld_value(fldvID) (id, name, value) = res[0] output = "" subtitle = """Modify existing value""" output = """
Warning: Modifications done below will also inflict on all places the modified data is used.
""" text = """ Display name
Search value
""" % (name, value) output += createhiddenform(action="%s/admin/websearch/websearchadmin.py/modifyfieldvalue" % CFG_SITE_URL, text=text, colID=colID, fldID=fldID, fldvID=fldvID, ln=ln, button="Update", confirm=1) output += createhiddenform(action="%s/admin/websearch/websearchadmin.py/modifyfieldvalue" % CFG_SITE_URL, text="Delete value and all associations", colID=colID, fldID=fldID, fldvID=fldvID, ln=ln, button="Delete", confirm=2) if name and value and confirm in ["1", 1]: res = update_fldv(fldvID, name, value) output += write_outcome(res) #if res: # output += """Operation successfully completed.""" #else: # output += """Operation failed.""" elif confirm in ["2", 2]: res = delete_fldv(fldvID) output += write_outcome(res) elif confirm not in ["-1", -1]: output += """Please fill in name and value.""" body = [output] output = "
" + addadminbox(subtitle, body) return perform_modifyfield(colID, fldID=fldID, ln=ln, content=output) def perform_removefield(colID, ln, fldID='', fldvID='', fmeth='', callback='yes', confirm=0): """form to remove a field from a collection. colID - the current collection, remove the field from this collection. sel_ln - remove the field with this language fldID - remove the field with this id""" if fmeth == "soo": field = "sort option" elif fmeth == "sew": field = "search field" elif fmeth == "seo": field = "search option" else: field = "field" subtitle = """Remove %s""" % field output = "" col_dict = dict(get_def_name('', "collection")) fld_dict = dict(get_def_name('', "field")) res = get_fld_value() fldv_dict = dict(map(lambda x: (x[0], x[1]), res)) if colID and fldID: colID = int(colID) fldID = int(fldID) if fldvID and fldvID != "None": fldvID = int(fldvID) if confirm in ["0", 0]: text = """Do you want to remove the %s '%s' %s from the collection '%s'.""" % (field, fld_dict[fldID], (fldvID not in["", "None"] and "with value '%s'" % fldv_dict[fldvID] or ''), col_dict[colID]) output += createhiddenform(action="removefield#6.5", text=text, button="Confirm", colID=colID, fldID=fldID, fldvID=fldvID, fmeth=fmeth, confirm=1) elif confirm in ["1", 1]: res = remove_fld(colID, fldID, fldvID) output += write_outcome(res) body = [output] output = "
" + addadminbox(subtitle, body) if fmeth == "soo": return perform_showsortoptions(colID, ln, content=output) elif fmeth == "sew": return perform_showsearchfields(colID, ln, content=output) elif fmeth == "seo": return perform_showsearchoptions(colID, ln, content=output) def perform_removefieldvalue(colID, ln, fldID='', fldvID='', fmeth='', callback='yes', confirm=0): """form to remove a field from a collection. colID - the current collection, remove the field from this collection. sel_ln - remove the field with this language fldID - remove the field with this id""" subtitle = """Remove value""" output = "" col_dict = dict(get_def_name('', "collection")) fld_dict = dict(get_def_name('', "field")) res = get_fld_value() fldv_dict = dict(map(lambda x: (x[0], x[1]), res)) if colID and fldID: colID = int(colID) fldID = int(fldID) if fldvID and fldvID != "None": fldvID = int(fldvID) if confirm in ["0", 0]: text = """Do you want to remove the value '%s' from the search option '%s'.""" % (fldv_dict[fldvID], fld_dict[fldID]) output += createhiddenform(action="removefieldvalue#7.4", text=text, button="Confirm", colID=colID, fldID=fldID, fldvID=fldvID, fmeth=fmeth, confirm=1) elif confirm in ["1", 1]: res = remove_fld(colID, fldID, fldvID) output += write_outcome(res) body = [output] output = "
" + addadminbox(subtitle, body) return perform_modifyfield(colID, fldID=fldID, ln=ln, content=output) def perform_rearrangefieldvalue(colID, fldID, ln, callback='yes', confirm=-1): """rearrang the fieldvalues alphabetically colID - the collection fldID - the field to rearrange the fieldvalue for """ subtitle = "Order values alphabetically" output = "" col_fldv = get_col_fld(colID, 'seo', fldID) col_fldv = dict(map(lambda x: (x[1], x[0]), col_fldv)) fldv_names = get_fld_value() fldv_names = map(lambda x: (x[0], x[1]), fldv_names) if not col_fldv.has_key(None): vscore = len(col_fldv) for (fldvID, name) in fldv_names: if col_fldv.has_key(fldvID): run_sql("UPDATE collection_field_fieldvalue SET score_fieldvalue=%s WHERE id_collection=%s and id_field=%s and id_fieldvalue=%s", (vscore, colID, fldID, fldvID)) vscore -= 1 output += write_outcome((1, "")) else: output += write_outcome((0, (0, "No values to order"))) body = [output] output = "
" + addadminbox(subtitle, body) return perform_modifyfield(colID, fldID, ln, content=output) def perform_rearrangefield(colID, ln, fmeth, callback='yes', confirm=-1): """rearrang the fields alphabetically colID - the collection """ subtitle = "Order fields alphabetically" output = "" col_fld = dict(map(lambda x: (x[0], x[1]), get_col_fld(colID, fmeth))) fld_names = get_def_name('', "field") if len(col_fld) > 0: score = len(col_fld) for (fldID, name) in fld_names: if col_fld.has_key(fldID): run_sql("UPDATE collection_field_fieldvalue SET score=%s WHERE id_collection=%s and id_field=%s", (score, colID, fldID)) score -= 1 output += write_outcome((1, "")) else: output += write_outcome((0, (0, "No fields to order"))) body = [output] output = "
" + addadminbox(subtitle, body) if fmeth == "soo": return perform_showsortoptions(colID, ln, content=output) elif fmeth == "sew": return perform_showsearchfields(colID, ln, content=output) elif fmeth == "seo": return perform_showsearchoptions(colID, ln, content=output) def perform_addexistingfieldvalue(colID, fldID, fldvID=-1, ln=CFG_SITE_LANG, callback='yes', confirm=-1): """form to add an existing fieldvalue to a field. colID - the collection fldID - the field to add the fieldvalue to fldvID - the fieldvalue to add""" subtitle = """Add existing value to search option""" output = "" if fldvID not in [-1, "-1"] and confirm in [1, "1"]: fldvID = int(fldvID) ares = add_col_fld(colID, fldID, 'seo', fldvID) colID = int(colID) fldID = int(fldID) lang = dict(get_languages()) res = get_def_name('', "field") col_dict = dict(get_def_name('', "collection")) fld_dict = dict(res) col_fld = dict(map(lambda x: (x[0], x[1]), get_col_fld(colID, 'seo'))) fld_value = get_fld_value() fldv_dict = dict(map(lambda x: (x[0], x[1]), fld_value)) text = """ Value
""" output += createhiddenform(action="addexistingfieldvalue#7.4", text=text, button="Add", colID=colID, fldID=fldID, ln=ln, confirm=1) if fldvID not in [-1, "-1"] and confirm in [1, "1"]: output += write_outcome(ares) elif confirm in [1, "1"]: output += """Select a value to add and try again.""" body = [output] output = "
" + addadminbox(subtitle, body) return perform_modifyfield(colID, fldID, ln, content=output) def perform_addexistingfield(colID, ln, fldID=-1, fldvID=-1, fmeth='', callback='yes', confirm=-1): """form to add an existing field to a collection. colID - the collection to add the field to fldID - the field to add sel_ln - the language of the field""" subtitle = """Add existing field to collection""" output = "" if fldID not in [-1, "-1"] and confirm in [1, "1"]: fldID = int(fldID) ares = add_col_fld(colID, fldID, fmeth, fldvID) colID = int(colID) lang = dict(get_languages()) res = get_def_name('', "field") col_dict = dict(get_def_name('', "collection")) fld_dict = dict(res) col_fld = dict(map(lambda x: (x[0], x[1]), get_col_fld(colID, fmeth))) fld_value = get_fld_value() fldv_dict = dict(map(lambda x: (x[0], x[1]), fld_value)) if fldvID: fldvID = int(fldvID) text = """ Field
""" output += createhiddenform(action="addexistingfield#6.2", text=text, button="Add", colID=colID, fmeth=fmeth, ln=ln, confirm=1) if fldID not in [-1, "-1"] and confirm in [1, "1"]: output += write_outcome(ares) elif fldID in [-1, "-1"] and confirm not in [-1, "-1"]: output += """Select a field. """ body = [output] output = "
" + addadminbox(subtitle, body) if fmeth == "soo": return perform_showsortoptions(colID, ln, content=output) elif fmeth == "sew": return perform_showsearchfields(colID, ln, content=output) elif fmeth == "seo": return perform_showsearchoptions(colID, ln, content=output) def perform_showsortoptions(colID, ln, callback='yes', content='', confirm=-1): """show the sort fields of this collection..""" colID = int(colID) col_dict = dict(get_def_name('', "collection")) fld_dict = dict(get_def_name('', "field")) fld_type = get_sort_nametypes() subtitle = """8. Modify sort options for collection '%s'   [?]""" % (col_dict[colID], CFG_SITE_URL) output = """
Field actions (not related to this collection)
Go to the BibIndex interface to modify the available sort options
Collection specific actions
Add sort option to collection
Order sort options alphabetically
""" % (colID, ln, colID, ln) header = ['', 'Sort option', 'Actions'] actions = [] sitelangs = get_languages() lang = dict(sitelangs) fld_type_list = fld_type.items() if len(get_col_fld(colID, 'soo')) > 0: res = get_col_fld(colID, 'soo') i = 0 for (fldID, fldvID, stype, score, score_fieldvalue) in res: move = """
""" if i != 0: move += """""" % (CFG_SITE_URL, colID, ln, fldID, res[i - 1][0], random.randint(0, 1000), CFG_SITE_URL) else: move += "    " move += "" i += 1 if i != len(res): move += """""" % (CFG_SITE_URL, colID, ln, fldID, res[i][0], random.randint(0, 1000), CFG_SITE_URL) move += """
""" actions.append([move, fld_dict[int(fldID)]]) for col in [(('Remove sort option', 'removefield'),)]: actions[-1].append('%s' % (CFG_SITE_URL, col[0][1], colID, ln, fldID, col[0][0])) for (str, function) in col[1:]: actions[-1][-1] += ' / %s' % (CFG_SITE_URL, function, colID, ln, fldID, str) output += tupletotable(header=header, tuple=actions) else: output += """No sort options exists for this collection""" output += content body = [output] if callback: return perform_editcollection(colID, ln, "perform_showsortoptions", addadminbox(subtitle, body)) else: return addadminbox(subtitle, body) def perform_showsearchfields(colID, ln, callback='yes', content='', confirm=-1): """show the search fields of this collection..""" colID = int(colID) col_dict = dict(get_def_name('', "collection")) fld_dict = dict(get_def_name('', "field")) fld_type = get_sort_nametypes() subtitle = """6. Modify search fields for collection '%s'   [?]""" % (col_dict[colID], CFG_SITE_URL) output = """
Field actions (not related to this collection)
Go to the BibIndex interface to modify the available search fields
Collection specific actions
Add search field to collection
Order search fields alphabetically
""" % (colID, ln, colID, ln) header = ['', 'Search field', 'Actions'] actions = [] sitelangs = get_languages() lang = dict(sitelangs) fld_type_list = fld_type.items() if len(get_col_fld(colID, 'sew')) > 0: res = get_col_fld(colID, 'sew') i = 0 for (fldID, fldvID, stype, score, score_fieldvalue) in res: move = """
""" if i != 0: move += """""" % (CFG_SITE_URL, colID, ln, fldID, res[i - 1][0], random.randint(0, 1000), CFG_SITE_URL) else: move += "   " move += "" i += 1 if i != len(res): move += '' % (CFG_SITE_URL, colID, ln, fldID, res[i][0], random.randint(0, 1000), CFG_SITE_URL) move += """
""" actions.append([move, fld_dict[int(fldID)]]) for col in [(('Remove search field', 'removefield'),)]: actions[-1].append('%s' % (CFG_SITE_URL, col[0][1], colID, ln, fldID, col[0][0])) for (str, function) in col[1:]: actions[-1][-1] += ' / %s' % (CFG_SITE_URL, function, colID, ln, fldID, str) output += tupletotable(header=header, tuple=actions) else: output += """No search fields exists for this collection""" output += content body = [output] if callback: return perform_editcollection(colID, ln, "perform_showsearchfields", addadminbox(subtitle, body)) else: return addadminbox(subtitle, body) def perform_showsearchoptions(colID, ln, callback='yes', content='', confirm=-1): """show the sort and search options of this collection..""" colID = int(colID) col_dict = dict(get_def_name('', "collection")) fld_dict = dict(get_def_name('', "field")) fld_type = get_sort_nametypes() subtitle = """7. Modify search options for collection '%s'   [?]""" % (col_dict[colID], CFG_SITE_URL) output = """
Field actions (not related to this collection)
Go to the BibIndex interface to modify the available search options
Collection specific actions
Add search option to collection
Order search options alphabetically
""" % (colID, ln, colID, ln) header = ['', 'Search option', 'Actions'] actions = [] sitelangs = get_languages() lang = dict(sitelangs) fld_type_list = fld_type.items() fld_distinct = run_sql("SELECT distinct(id_field) FROM collection_field_fieldvalue WHERE type='seo' AND id_collection=%s ORDER by score desc", (colID, )) if len(fld_distinct) > 0: i = 0 for (id) in fld_distinct: fldID = id[0] col_fld = get_col_fld(colID, 'seo', fldID) move = "" if i != 0: move += """""" % (CFG_SITE_URL, colID, ln, fldID, fld_distinct[i - 1][0], random.randint(0, 1000), CFG_SITE_URL) else: move += "   " i += 1 if i != len(fld_distinct): move += '' % (CFG_SITE_URL, colID, ln, fldID, fld_distinct[i][0], random.randint(0, 1000), CFG_SITE_URL) actions.append([move, "%s" % fld_dict[fldID]]) for col in [(('Modify values', 'modifyfield'), ('Remove search option', 'removefield'),)]: actions[-1].append('%s' % (CFG_SITE_URL, col[0][1], colID, ln, fldID, col[0][0])) for (str, function) in col[1:]: actions[-1][-1] += ' / %s' % (CFG_SITE_URL, function, colID, ln, fldID, str) output += tupletotable(header=header, tuple=actions) else: output += """No search options exists for this collection""" output += content body = [output] if callback: return perform_editcollection(colID, ln, "perform_showsearchoptions", addadminbox(subtitle, body)) else: return addadminbox(subtitle, body) def perform_modifyfield(colID, fldID, fldvID='', ln=CFG_SITE_LANG, content='', callback='yes', confirm=0): """Modify the fieldvalues for a field""" colID = int(colID) col_dict = dict(get_def_name('', "collection")) fld_dict = dict(get_def_name('', "field")) fld_type = get_sort_nametypes() fldID = int(fldID) subtitle = """Modify values for field '%s'""" % (fld_dict[fldID]) output = """
Value specific actions
Add existing value to search option
Add new value to search option
Order values alphabetically
""" % (colID, ln, fldID, colID, ln, fldID, colID, ln, fldID) header = ['', 'Value name', 'Actions'] actions = [] sitelangs = get_languages() lang = dict(sitelangs) fld_type_list = fld_type.items() col_fld = list(get_col_fld(colID, 'seo', fldID)) if len(col_fld) == 1 and col_fld[0][1] is None: output += """No values added for this search option yet""" else: j = 0 for (fldID, fldvID, stype, score, score_fieldvalue) in col_fld: fieldvalue = get_fld_value(fldvID) move = "" if j != 0: move += """""" % (CFG_SITE_URL, colID, ln, fldID, fldvID, col_fld[j - 1][1], random.randint(0, 1000), CFG_SITE_URL) else: move += "   " j += 1 if j != len(col_fld): move += """""" % (CFG_SITE_URL, colID, ln, fldID, fldvID, col_fld[j][1], random.randint(0, 1000), CFG_SITE_URL) if fieldvalue[0][1] != fieldvalue[0][2] and fldvID is not None: actions.append([move, "%s - %s" % (fieldvalue[0][1], fieldvalue[0][2])]) elif fldvID is not None: actions.append([move, "%s" % fieldvalue[0][1]]) move = '' for col in [(('Modify value', 'modifyfieldvalue'), ('Remove value', 'removefieldvalue'),)]: actions[-1].append('%s' % (CFG_SITE_URL, col[0][1], colID, ln, fldID, fldvID, col[0][0])) for (str, function) in col[1:]: actions[-1][-1] += ' / %s' % (CFG_SITE_URL, function, colID, ln, fldID, fldvID, str) output += tupletotable(header=header, tuple=actions) output += content body = [output] output = "
" + addadminbox(subtitle, body) if len(col_fld) == 0: output = content return perform_showsearchoptions(colID, ln, content=output) def perform_showoutputformats(colID, ln, callback='yes', content='', confirm=-1): """shows the outputformats of the current collection colID - the collection id.""" colID = int(colID) col_dict = dict(get_def_name('', "collection")) subtitle = """10. Modify output formats for collection '%s'   [?]""" % (col_dict[colID], CFG_SITE_URL) output = """
Output format actions (not specific to the chosen collection)
Go to the BibFormat interface to modify
Collection specific actions
Add existing output format to collection
""" % (colID, ln) header = ['', 'Code', 'Output format', 'Actions'] actions = [] col_fmt = get_col_fmt(colID) fmt_dict = dict(get_def_name('', "format")) i = 0 if len(col_fmt) > 0: for (id_format, colID_fld, code, score) in col_fmt: move = """
""" if i != 0: move += """""" % (CFG_SITE_URL, colID, ln, id_format, col_fmt[i - 1][0], random.randint(0, 1000), CFG_SITE_URL) else: move += "   " move += "" i += 1 if i != len(col_fmt): move += '' % (CFG_SITE_URL, colID, ln, id_format, col_fmt[i][0], random.randint(0, 1000), CFG_SITE_URL) move += """
""" actions.append([move, code, fmt_dict[int(id_format)]]) for col in [(('Remove', 'removeoutputformat'),)]: actions[-1].append('%s' % (CFG_SITE_URL, col[0][1], colID, ln, id_format, col[0][0])) for (str, function) in col[1:]: actions[-1][-1] += ' / %s' % (CFG_SITE_URL, function, colID, ln, id_format, str) output += tupletotable(header=header, tuple=actions) else: output += """No output formats exists for this collection""" output += content body = [output] if callback: return perform_editcollection(colID, ln, "perform_showoutputformats", addadminbox(subtitle, body)) else: return addadminbox(subtitle, body) def external_collections_build_select(colID, external_collection): output = '\n' return output def perform_manage_external_collections(colID, ln, callback='yes', content='', confirm=-1): """Show the interface to configure external collections to the user.""" colID = int(colID) subtitle = """11. Configuration of related external collections    [?]""" % CFG_SITE_URL output = '
' % {'colID': colID} table_header = ['External collection', 'Mode', 'Apply also to daughter collections?'] table_content = [] external_collections = external_collection_sort_engine_by_name(external_collections_dictionary.values()) for external_collection in external_collections: collection_name = external_collection.name select = external_collections_build_select(colID, external_collection) recurse = '' % {'collection_name': collection_name} table_content.append([collection_name, select, recurse]) output += tupletotable(header=table_header, tuple=table_content) output += '' output += '
' return addadminbox(subtitle, [output]) def perform_update_external_collections(colID, ln, state_list, recurse_list): colID = int(colID) changes = [] output = "" if not state_list: return 'Warning : No state found.
' + perform_manage_external_collections(colID, ln) external_collections = external_collection_sort_engine_by_name(external_collections_dictionary.values()) if len(external_collections) != len(state_list): return 'Warning : Size of state_list different from external_collections!
' + perform_manage_external_collections(colID, ln) for (external_collection, state) in zip(external_collections, state_list): state = int(state) collection_name = external_collection.name recurse = recurse_list and collection_name in recurse_list oldstate = external_collection_get_state(external_collection, colID) if oldstate != state or recurse: changes += external_collection_get_update_state_list(external_collection, colID, state, recurse) external_collection_apply_changes(changes) return output + '

' + perform_manage_external_collections(colID, ln) def perform_showdetailedrecordoptions(colID, ln, callback='yes', content='', confirm=-1): """Show the interface to configure detailed record page to the user.""" colID = int(colID) subtitle = """12. Configuration of detailed record page    [?]""" % CFG_SITE_URL output = '''
Show tabs:
''' % {'colID': colID} for (tab_id, tab_info) in get_detailed_page_tabs(colID).iteritems(): if tab_id == 'comments' and \ not CFG_WEBCOMMENT_ALLOW_REVIEWS and \ not CFG_WEBCOMMENT_ALLOW_COMMENTS: continue check = '' output += '''
''' % {'tabid':tab_id, 'check':((tab_info['visible'] and 'checked="checked"') or ''), 'label':tab_info['label']} output += '
' output += '
' output += ''' ''' output += '
' return addadminbox(subtitle, [output]) def perform_update_detailed_record_options(colID, ln, tabs, recurse): """Update the preferences for the tab to show/hide in the detailed record page.""" colID = int(colID) changes = [] output = 'Operation successfully completed.' if '' in tabs: tabs.remove('') tabs.append('metadata') def update_settings(colID, tabs, recurse): run_sql("DELETE FROM collectiondetailedrecordpagetabs WHERE id_collection=%s", (colID, )) run_sql("REPLACE INTO collectiondetailedrecordpagetabs" + \ " SET id_collection=%s, tabs=%s", (colID, ';'.join(tabs))) ## for enabled_tab in tabs: ## run_sql("REPLACE INTO collectiondetailedrecordpagetabs" + \ ## " SET id_collection='%s', tabs='%s'" % (colID, ';'.join(tabs))) if recurse: for descendant_id in get_collection_descendants(colID): update_settings(descendant_id, tabs, recurse) update_settings(colID, tabs, recurse) ## for colID in colIDs: ## run_sql("DELETE FROM collectiondetailedrecordpagetabs WHERE id_collection='%s'" % colID) ## for enabled_tab in tabs: ## run_sql("REPLACE INTO collectiondetailedrecordpagetabs" + \ ## " SET id_collection='%s', tabs='%s'" % (colID, ';'.join(tabs))) #if callback: return perform_editcollection(colID, ln, "perform_modifytranslations", '

' + output + '

' + \ perform_showdetailedrecordoptions(colID, ln)) #else: # return addadminbox(subtitle, body) #return output + '

' + perform_showdetailedrecordoptions(colID, ln) def perform_addexistingoutputformat(colID, ln, fmtID=-1, callback='yes', confirm=-1): """form to add an existing output format to a collection. colID - the collection the format should be added to fmtID - the format to add.""" subtitle = """Add existing output format to collection""" output = "" if fmtID not in [-1, "-1"] and confirm in [1, "1"]: ares = add_col_fmt(colID, fmtID) colID = int(colID) res = get_def_name('', "format") fmt_dict = dict(res) col_dict = dict(get_def_name('', "collection")) col_fmt = get_col_fmt(colID) col_fmt = dict(map(lambda x: (x[0], x[2]), col_fmt)) if len(res) > 0: text = """ Output format
""" output += createhiddenform(action="addexistingoutputformat#10.2", text=text, button="Add", colID=colID, ln=ln, confirm=1) else: output = """No existing output formats to add, please create a new one.""" if fmtID not in [-1, "-1"] and confirm in [1, "1"]: output += write_outcome(ares) elif fmtID in [-1, "-1"] and confirm not in [-1, "-1"]: output += """Please select output format.""" body = [output] output = "
" + addadminbox(subtitle, body) return perform_showoutputformats(colID, ln, content=output) def perform_deleteoutputformat(colID, ln, fmtID=-1, callback='yes', confirm=-1): """form to delete an output format not in use. colID - the collection id of the current collection. fmtID - the format id to delete.""" subtitle = """Delete an unused output format""" output = """
Deleting an output format will also delete the translations associated.
""" colID = int(colID) if fmtID not in [-1, "-1"] and confirm in [1, "1"]: fmt_dict = dict(get_def_name('', "format")) old_colNAME = fmt_dict[int(fmtID)] ares = delete_fmt(int(fmtID)) res = get_def_name('', "format") fmt_dict = dict(res) col_dict = dict(get_def_name('', "collection")) col_fmt = get_col_fmt() col_fmt = dict(map(lambda x: (x[0], x[2]), col_fmt)) if len(res) > 0: text = """ Output format
""" output += createhiddenform(action="deleteoutputformat#10.3", text=text, button="Delete", colID=colID, ln=ln, confirm=0) if fmtID not in [-1, "-1"]: fmtID = int(fmtID) if confirm in [0, "0"]: text = """Do you want to delete the output format '%s'. """ % fmt_dict[fmtID] output += createhiddenform(action="deleteoutputformat#10.3", text=text, button="Confirm", colID=colID, fmtID=fmtID, ln=ln, confirm=1) elif confirm in [1, "1"]: output += write_outcome(ares) elif confirm not in [-1, "-1"]: output += """Choose a output format to delete. """ body = [output] output = "
" + addadminbox(subtitle, body) return perform_showoutputformats(colID, ln, content=output) def perform_removeoutputformat(colID, ln, fmtID='', callback='yes', confirm=0): """form to remove an output format from a collection. colID - the collection id of the current collection. fmtID - the format id. """ subtitle = """Remove output format""" output = "" col_dict = dict(get_def_name('', "collection")) fmt_dict = dict(get_def_name('', "format")) if colID and fmtID: colID = int(colID) fmtID = int(fmtID) if confirm in ["0", 0]: text = """Do you want to remove the output format '%s' from the collection '%s'.""" % (fmt_dict[fmtID], col_dict[colID]) output += createhiddenform(action="removeoutputformat#10.5", text=text, button="Confirm", colID=colID, fmtID=fmtID, confirm=1) elif confirm in ["1", 1]: res = remove_fmt(colID, fmtID) output += write_outcome(res) body = [output] output = "
" + addadminbox(subtitle, body) return perform_showoutputformats(colID, ln, content=output) def perform_index(colID=1, ln=CFG_SITE_LANG, mtype='', content='', confirm=0): """The index method, calling methods to show the collection tree, create new collections and add collections to tree. """ subtitle = "Overview" colID = int(colID) col_dict = dict(get_def_name('', "collection")) output = "" fin_output = "" if not col_dict.has_key(1): res = add_col(CFG_SITE_NAME, '') if res: fin_output += """Created root collection.
""" else: return "Cannot create root collection, please check database." if CFG_SITE_NAME != run_sql("SELECT name from collection WHERE id=1")[0][0]: res = run_sql("update collection set name=%s where id=1", (CFG_SITE_NAME, )) if res: fin_output += """The name of the root collection has been modified to be the same as the %(sitename)s installation name given prior to installing %(sitename)s.
""" % {'sitename' : CFG_SITE_NAME} else: return "Error renaming root collection." fin_output += """
0. Show all 1. Create new collection 2. Attach collection to tree 3. Modify collection tree 4. Webcoll Status
5. Collection Status 6. Check external collections 7. Guide
""" % (CFG_SITE_URL, colID, ln, CFG_SITE_URL, colID, ln, CFG_SITE_URL, colID, ln, CFG_SITE_URL, colID, ln, CFG_SITE_URL, colID, ln, CFG_SITE_URL, colID, ln, CFG_SITE_URL, colID, ln, CFG_SITE_URL, ln) if mtype == "": fin_output += """

To manage the collections, select an item from the menu.
""" if mtype == "perform_addcollection" and content: fin_output += content elif mtype == "perform_addcollection" or mtype == "perform_showall": fin_output += perform_addcollection(colID=colID, ln=ln, callback='') fin_output += "
" if mtype == "perform_addcollectiontotree" and content: fin_output += content elif mtype == "perform_addcollectiontotree" or mtype == "perform_showall": fin_output += perform_addcollectiontotree(colID=colID, ln=ln, callback='') fin_output += "
" if mtype == "perform_modifycollectiontree" and content: fin_output += content elif mtype == "perform_modifycollectiontree" or mtype == "perform_showall": fin_output += perform_modifycollectiontree(colID=colID, ln=ln, callback='') fin_output += "
" if mtype == "perform_checkwebcollstatus" and content: fin_output += content elif mtype == "perform_checkwebcollstatus" or mtype == "perform_showall": fin_output += perform_checkwebcollstatus(colID, ln, callback='') if mtype == "perform_checkcollectionstatus" and content: fin_output += content elif mtype == "perform_checkcollectionstatus" or mtype == "perform_showall": fin_output += perform_checkcollectionstatus(colID, ln, callback='') if mtype == "perform_checkexternalcollections" and content: fin_output += content elif mtype == "perform_checkexternalcollections" or mtype == "perform_showall": fin_output += perform_checkexternalcollections(colID, ln, callback='') body = [fin_output] body = [fin_output] return addadminbox('Menu', body) def show_coll_not_in_tree(colID, ln, col_dict): """Returns collections not in tree""" tree = get_col_tree(colID) in_tree = {} output = "These collections are not in the tree, and should be added:
" for (id, up, down, dad, reltype) in tree: in_tree[id] = 1 in_tree[dad] = 1 res = run_sql("SELECT id from collection") if len(res) != len(in_tree): for id in res: if not in_tree.has_key(id[0]): output += """%s , """ % (CFG_SITE_URL, id[0], ln, col_dict[id[0]]) output += "

" else: output = "" return output def create_colltree(tree, col_dict, colID, ln, move_from='', move_to='', rtype='', edit=''): """Creates the presentation of the collection tree, with the buttons for modifying it. tree - the tree to present, from get_tree() col_dict - the name of the collections in a dictionary colID - the collection id to start with move_from - if a collection to be moved has been chosen move_to - the collection which should be set as father of move_from rtype - the type of the tree, regular or virtual edit - if the method should output the edit buttons.""" if move_from: move_from_rtype = move_from[0] move_from_id = int(move_from[1:len(move_from)]) tree_from = get_col_tree(colID, move_from_rtype) tree_to = get_col_tree(colID, rtype) tables = 0 tstack = [] i = 0 text = """ """ for i in range(0, len(tree)): id_son = tree[i][0] up = tree[i][1] down = tree[i][2] dad = tree[i][3] reltype = tree[i][4] tmove_from = "" j = i while j > 0: j = j - 1 try: if tstack[j][1] == dad: table = tstack[j][2] for k in range(0, tables - table): tables = tables - 1 text += """
""" break except StandardError, e: pass text += """ """ if i > 0 and tree[i][1] == 0: tables = tables + 1 text += """ """ while tables > 0: text += """
""" if i == 0: tstack.append((id_son, dad, 1)) else: tstack.append((id_son, dad, tables)) if up == 1 and edit: text += """""" % (CFG_SITE_URL, colID, ln, i, rtype, tree[i][0], CFG_SITE_URL) else: text += """ """ text += "" if down == 1 and edit: text += """""" % (CFG_SITE_URL, colID, ln, i, rtype, tree[i][0], CFG_SITE_URL) else: text += """ """ text += "" if edit: if move_from and move_to: tmove_from = move_from move_from = '' if not (move_from == "" and i == 0) and not (move_from != "" and int(move_from[1:len(move_from)]) == i and rtype == move_from[0]): check = "true" if move_from: #if tree_from[move_from_id][0] == tree_to[i][0] or not check_col(tree_to[i][0], tree_from[move_from_id][0]): # check = '' #elif not check_col(tree_to[i][0], tree_from[move_from_id][0]): # check = '' #if not check and (tree_to[i][0] == 1 and tree_from[move_from_id][3] == tree_to[i][0] and move_from_rtype != rtype): # check = "true" if check: text += """ """ % (CFG_SITE_URL, colID, ln, move_from, rtype, i, rtype, CFG_SITE_URL, col_dict[tree_from[int(move_from[1:len(move_from)])][0]], col_dict[tree_to[i][0]]) else: try: text += """""" % (CFG_SITE_URL, colID, ln, rtype, i, rtype, tree[i][0], CFG_SITE_URL, col_dict[tree[i][0]]) except KeyError: pass else: text += """ """ % CFG_SITE_URL else: text += """ """ % CFG_SITE_URL text += """ """ if edit: try: text += """""" % (CFG_SITE_URL, colID, ln, i, rtype, tree[i][0], CFG_SITE_URL) except KeyError: pass elif i != 0: text += """ """ % CFG_SITE_URL text += """ """ if tmove_from: move_from = tmove_from try: text += """%s%s%s%s%s""" % (tree[i][0], (reltype=="v" and '' or ''), CFG_SITE_URL, tree[i][0], ln, col_dict[id_son], (move_to=="%s%s" %(rtype, i) and ' ' % CFG_SITE_URL or ''), (move_from=="%s%s" % (rtype, i) and ' ' % CFG_SITE_URL or ''), (reltype=="v" and '' or '')) except KeyError: pass text += """
""" tables = tables - 1 text += """ """ return text def perform_deletecollection(colID, ln, confirm=-1, callback='yes'): """form to delete a collection colID - id of collection """ subtitle ='' output = """
WARNING:
When deleting a collection, you also deletes all data related to the collection like translations, relations to other collections and information about which rank methods to use.
For more information, please go to the WebSearch guide and read the section regarding deleting a collection.
""" % CFG_SITE_URL col_dict = dict(get_def_name('', "collection")) if colID != 1 and colID and col_dict.has_key(int(colID)): colID = int(colID) subtitle = """4. Delete collection '%s'   [?]""" % (col_dict[colID], CFG_SITE_URL) res = run_sql("SELECT id_dad,id_son,type,score from collection_collection WHERE id_dad=%s", (colID, )) res2 = run_sql("SELECT id_dad,id_son,type,score from collection_collection WHERE id_son=%s", (colID, )) if not res and not res2: if confirm in ["-1", -1]: text = """Do you want to delete this collection.""" output += createhiddenform(action="deletecollection#4", text=text, colID=colID, button="Delete", confirm=0) elif confirm in ["0", 0]: text = """Are you sure you want to delete this collection.""" output += createhiddenform(action="deletecollection#4", text=text, colID=colID, button="Confirm", confirm=1) elif confirm in ["1", 1]: result = delete_col(colID) if not result: raise Exception else: output = """Can not delete a collection that is a part of the collection tree, remove collection from the tree and try again.""" else: subtitle = """4. Delete collection""" output = """Not possible to delete the root collection""" body = [output] if callback: return perform_editcollection(colID, ln, "perform_deletecollection", addadminbox(subtitle, body)) else: return addadminbox(subtitle, body) def perform_editcollection(colID=1, ln=CFG_SITE_LANG, mtype='', content=''): """interface to modify a collection. this method is calling other methods which again is calling this and sending back the output of the method. if callback, the method will call perform_editcollection, if not, it will just return its output. colID - id of the collection mtype - the method that called this method. content - the output from that method.""" colID = int(colID) col_dict = dict(get_def_name('', "collection")) if not col_dict.has_key(colID): return """Collection deleted. """ fin_output = """
Menu
0. Show all 1. Modify collection query 2. Modify access restrictions 3. Modify translations 4. Delete collection
5. Modify portalboxes 6. Modify search fields 7. Modify search options 8. Modify sort options 9. Modify rank options
10. Modify output formats 11. Configuration of related external collections 12. Detailed record page options
""" % (colID, ln, colID, ln, colID, ln, colID, ln, colID, ln, colID, ln, colID, ln, colID, ln, colID, ln, colID, ln, colID, ln, colID, ln, colID, ln) if mtype == "perform_modifydbquery" and content: fin_output += content elif mtype == "perform_modifydbquery" or not mtype: fin_output += perform_modifydbquery(colID, ln, callback='') if mtype == "perform_modifyrestricted" and content: fin_output += content elif mtype == "perform_modifyrestricted" or not mtype: fin_output += perform_modifyrestricted(colID, ln, callback='') if mtype == "perform_modifytranslations" and content: fin_output += content elif mtype == "perform_modifytranslations" or not mtype: fin_output += perform_modifytranslations(colID, ln, callback='') if mtype == "perform_deletecollection" and content: fin_output += content elif mtype == "perform_deletecollection" or not mtype: fin_output += perform_deletecollection(colID, ln, callback='') if mtype == "perform_showportalboxes" and content: fin_output += content elif mtype == "perform_showportalboxes" or not mtype: fin_output += perform_showportalboxes(colID, ln, callback='') if mtype == "perform_showsearchfields" and content: fin_output += content elif mtype == "perform_showsearchfields" or not mtype: fin_output += perform_showsearchfields(colID, ln, callback='') if mtype == "perform_showsearchoptions" and content: fin_output += content elif mtype == "perform_showsearchoptions" or not mtype: fin_output += perform_showsearchoptions(colID, ln, callback='') if mtype == "perform_showsortoptions" and content: fin_output += content elif mtype == "perform_showsortoptions" or not mtype: fin_output += perform_showsortoptions(colID, ln, callback='') if mtype == "perform_modifyrankmethods" and content: fin_output += content elif mtype == "perform_modifyrankmethods" or not mtype: fin_output += perform_modifyrankmethods(colID, ln, callback='') if mtype == "perform_showoutputformats" and content: fin_output += content elif mtype == "perform_showoutputformats" or not mtype: fin_output += perform_showoutputformats(colID, ln, callback='') if mtype == "perform_manage_external_collections" and content: fin_output += content elif mtype == "perform_manage_external_collections" or not mtype: fin_output += perform_manage_external_collections(colID, ln, callback='') if mtype == "perform_showdetailedrecordoptions" and content: fin_output += content elif mtype == "perform_showdetailedrecordoptions" or not mtype: fin_output += perform_showdetailedrecordoptions(colID, ln, callback='') return addadminbox("Overview of edit options for collection '%s'" % col_dict[colID], [fin_output]) def perform_checkwebcollstatus(colID, ln, confirm=0, callback='yes'): """Check status of the collection tables with respect to the webcoll cache.""" subtitle = """Webcoll Status   [?]""" % CFG_SITE_URL output = "" colID = int(colID) col_dict = dict(get_def_name('', "collection")) output += """
Last updates:
""" collection_table_update_time = "" collection_web_update_time = "" collection_table_update_time = get_table_update_time('collection') output += "Collection table last updated: %s
" % collection_table_update_time try: file = open("%s/collections/last_updated" % CFG_CACHEDIR) collection_web_update_time = file.readline().strip() output += "Collection cache last updated: %s
" % collection_web_update_time file.close() except: pass # reformat collection_web_update_time to the format suitable for comparisons try: collection_web_update_time = time.strftime("%Y-%m-%d %H:%M:%S", time.strptime(collection_web_update_time, "%d %b %Y %H:%M:%S")) except ValueError, e: pass if collection_table_update_time > collection_web_update_time: output += """
Warning: The collections have been modified since last time Webcoll was executed, to process the changes, Webcoll must be executed.
""" header = ['ID', 'Name', 'Time', 'Status', 'Progress'] actions = [] output += """
Last BibSched tasks:
""" res = run_sql("select id, proc, host, user, runtime, sleeptime, arguments, status, progress from schTASK where proc='webcoll' and runtime< now() ORDER by runtime") if len(res) > 0: (id, proc, host, user, runtime, sleeptime, arguments, status, progress) = res[len(res) - 1] webcoll__update_time = runtime actions.append([id, proc, runtime, (status !="" and status or ''), (progress !="" and progress or '')]) else: actions.append(['', 'webcoll', '', '', 'Not executed yet']) res = run_sql("select id, proc, host, user, runtime, sleeptime, arguments, status, progress from schTASK where proc='bibindex' and runtime< now() ORDER by runtime") if len(res) > 0: (id, proc, host, user, runtime, sleeptime, arguments, status, progress) = res[len(res) - 1] actions.append([id, proc, runtime, (status !="" and status or ''), (progress !="" and progress or '')]) else: actions.append(['', 'bibindex', '', '', 'Not executed yet']) output += tupletotable(header=header, tuple=actions) output += """
Next scheduled BibSched run:
""" actions = [] res = run_sql("select id, proc, host, user, runtime, sleeptime, arguments, status, progress from schTASK where proc='webcoll' and runtime > now() ORDER by runtime") webcoll_future = "" if len(res) > 0: (id, proc, host, user, runtime, sleeptime, arguments, status, progress) = res[0] webcoll__update_time = runtime actions.append([id, proc, runtime, (status !="" and status or ''), (progress !="" and progress or '')]) webcoll_future = "yes" else: actions.append(['', 'webcoll', '', '', 'Not scheduled']) res = run_sql("select id, proc, host, user, runtime, sleeptime, arguments, status, progress from schTASK where proc='bibindex' and runtime > now() ORDER by runtime") bibindex_future = "" if len(res) > 0: (id, proc, host, user, runtime, sleeptime, arguments, status, progress) = res[0] actions.append([id, proc, runtime, (status !="" and status or ''), (progress !="" and progress or '')]) bibindex_future = "yes" else: actions.append(['', 'bibindex', '', '', 'Not scheduled']) output += tupletotable(header=header, tuple=actions) if webcoll_future == "": output += """
Warning: Webcoll is not scheduled for a future run by bibsched, any updates to the collection will not be processed.
""" if bibindex_future == "": output += """
Warning: Bibindex is not scheduled for a future run by bibsched, any updates to the records will not be processed.
""" body = [output] if callback: return perform_index(colID, ln, "perform_checkwebcollstatus", addadminbox(subtitle, body)) else: return addadminbox(subtitle, body) def perform_modifyrestricted(colID, ln, rest='', callback='yes', confirm=-1): """modify which apache group is allowed to access the collection. rest - the groupname""" subtitle = '' output = "" col_dict = dict(get_def_name('', "collection")) action_id = acc_get_action_id(VIEWRESTRCOLL) if colID and col_dict.has_key(int(colID)): colID = int(colID) subtitle = """2. Modify access restrictions for collection '%s'   [?]""" % (col_dict[colID], CFG_SITE_URL) output = """

Please note that Invenio versions greater than 0.92.1 manage collection restriction via the standard WebAccess Admin Interface (action '%s').

""" % (action_id, VIEWRESTRCOLL) body = [output] if callback: return perform_editcollection(colID, ln, "perform_modifyrestricted", addadminbox(subtitle, body)) else: return addadminbox(subtitle, body) def perform_checkcollectionstatus(colID, ln, confirm=0, callback='yes'): """Check the configuration of the collections.""" from invenio.search_engine import collection_restricted_p subtitle = """Collection Status   [?]""" % CFG_SITE_URL output = "" colID = int(colID) col_dict = dict(get_def_name('', "collection")) collections = run_sql("SELECT id, name, dbquery, nbrecs FROM collection " "ORDER BY id") header = ['ID', 'Name','Query', 'Subcollections', 'Restricted', 'Hosted', 'I18N', 'Status', 'Number of records'] rnk_list = get_def_name('', "rnkMETHOD") actions = [] for (id, name, dbquery, nbrecs) in collections: reg_sons = len(get_col_tree(id, 'r')) vir_sons = len(get_col_tree(id, 'v')) status = "" hosted = "" if str(dbquery).startswith("hostedcollection:"): hosted = """Yes""" else: hosted = """No""" langs = run_sql("SELECT ln from collectionname where id_collection=%s", (id, )) i8n = "" if len(langs) > 0: for lang in langs: i8n += "%s, " % lang else: i8n = """None""" if (reg_sons > 1 and dbquery) or dbquery=="": status = """1:Query""" elif dbquery is None and reg_sons == 1: status = """2:Query""" elif dbquery == "" and reg_sons == 1: status = """3:Query""" if (reg_sons > 1 or vir_sons > 1): subs = """Yes""" else: subs = """No""" if dbquery is None: dbquery = """No""" restricted = collection_restricted_p(name) if restricted: restricted = """Yes""" if status: status += """,4:Restricted""" else: status += """4:Restricted""" else: restricted = """No""" if status == "": status = """OK""" actions.append([id, """%s""" % (CFG_SITE_URL, id, ln, name), dbquery, subs, restricted, hosted, i8n, status, nbrecs]) output += tupletotable(header=header, tuple=actions) body = [output] return addadminbox(subtitle, body) if callback: return perform_index(colID, ln, "perform_checkcollectionstatus", addadminbox(subtitle, body)) else: return addadminbox(subtitle, body) def perform_checkexternalcollections(colID, ln, icl=None, update="", confirm=0, callback='yes'): """Check the external collections for inconsistencies.""" subtitle = """Check external collections   [?]""" % CFG_SITE_URL output = "" colID = int(colID) if icl: if update == "add": # icl : the "inconsistent list" comes as a string, it has to be converted back into a list icl = eval(icl) #icl = icl[1:-1].split(',') for collection in icl: #collection = str(collection[1:-1]) query_select = "SELECT name FROM externalcollection WHERE name like '%(name)s';" % {'name': collection} results_select = run_sql(query_select) if not results_select: query_insert = "INSERT INTO externalcollection (name) VALUES ('%(name)s');" % {'name': collection} run_sql(query_insert) output += """
New collection \"%s\" has been added to the database table \"externalcollection\".
""" % (collection) else: output += """
Collection \"%s\" has already been added to the database table \"externalcollection\" or was already there.
""" % (collection) elif update == "del": # icl : the "inconsistent list" comes as a string, it has to be converted back into a list icl = eval(icl) #icl = icl[1:-1].split(',') for collection in icl: #collection = str(collection[1:-1]) query_select = "SELECT id FROM externalcollection WHERE name like '%(name)s';" % {'name': collection} results_select = run_sql(query_select) if results_select: query_delete = "DELETE FROM externalcollection WHERE id like '%(id)s';" % {'id': results_select[0][0]} query_delete_states = "DELETE FROM collection_externalcollection WHERE id_externalcollection like '%(id)s';" % {'id': results_select[0][0]} run_sql(query_delete) run_sql(query_delete_states) output += """
Collection \"%s\" has been deleted from the database table \"externalcollection\".
""" % (collection) else: output += """
Collection \"%s\" has already been delete from the database table \"externalcollection\" or was never there.
""" % (collection) external_collections_file = [] external_collections_db = [] for coll in external_collections_dictionary.values(): external_collections_file.append(coll.name) external_collections_file.sort() query = """SELECT name from externalcollection""" results = run_sql(query) for result in results: external_collections_db.append(result[0]) external_collections_db.sort() number_file = len(external_collections_file) number_db = len(external_collections_db) if external_collections_file == external_collections_db: output += """
External collections are consistent.

   - database table \"externalcollection\" has %(number_db)s collections
   - configuration file \"websearch_external_collections_config.py\" has %(number_file)s collections""" % { "number_db" : number_db, "number_file" : number_file} elif len(external_collections_file) > len(external_collections_db): external_collections_diff = list(set(external_collections_file) - set(external_collections_db)) external_collections_db.extend(external_collections_diff) external_collections_db.sort() if external_collections_file == external_collections_db: output += """
There is an inconsistency:

   - database table \"externalcollection\" has %(number_db)s collections  (missing: %(diff)s)
   - configuration file \"websearch_external_collections_config.py\" has %(number_file)s collections

Click here to update your database adding the missing collections. If the problem persists please check your configuration manually.""" % { "number_db" : number_db, "number_file" : number_file, "diff" : external_collections_diff, "site_url" : CFG_SITE_URL, "colID" : colID, "ln" : ln} else: output += """
There is an inconsistency:

   - database table \"externalcollection\" has %(number_db)s collections
   - configuration file \"websearch_external_collections_config.py\" has %(number_file)s collections

The external collections do not match.
To fix the problem please check your configuration manually.""" % { "number_db" : number_db, "number_file" : number_file} elif len(external_collections_file) < len(external_collections_db): external_collections_diff = list(set(external_collections_db) - set(external_collections_file)) external_collections_file.extend(external_collections_diff) external_collections_file.sort() if external_collections_file == external_collections_db: output += """
There is an inconsistency:

   - database table \"externalcollection\" has %(number_db)s collections  (extra: %(diff)s)
   - configuration file \"websearch_external_collections_config.py\" has %(number_file)s collections

Click here to force remove the extra collections from your database (warning: use with caution!). If the problem persists please check your configuration manually.""" % { "number_db" : number_db, "number_file" : number_file, "diff" : external_collections_diff, "site_url" : CFG_SITE_URL, "colID" : colID, "ln" : ln} else: output += """
There is an inconsistency:

   - database table \"externalcollection\" has %(number_db)s collections
   - configuration file \"websearch_external_collections_config.py\" has %(number_file)s collections

The external collections do not match.
To fix the problem please check your configuration manually.""" % { "number_db" : number_db, "number_file" : number_file} else: output += """
There is an inconsistency:

   - database table \"externalcollection\" has %(number_db)s collections
   - configuration file \"websearch_external_collections_config.py\" has %(number_file)s collections

The number of external collections is the same but the collections do not match.
To fix the problem please check your configuration manually.""" % { "number_db" : number_db, "number_file" : number_file} body = [output] return addadminbox(subtitle, body) if callback: return perform_index(colID, ln, "perform_checkexternalcollections", addadminbox(subtitle, body)) else: return addadminbox(subtitle, body) def get_col_tree(colID, rtype=''): """Returns a presentation of the tree as a list. TODO: Add loop detection colID - startpoint for the tree rtype - get regular or virtual part of the tree""" try: colID = int(colID) stack = [colID] ssize = 0 tree = [(colID, 0, 0, colID, 'r')] while len(stack) > 0: ccolID = stack.pop() if ccolID == colID and rtype: res = run_sql("SELECT id_son, score, type FROM collection_collection WHERE id_dad=%s AND type=%s ORDER BY score ASC,id_son", (ccolID, rtype)) else: res = run_sql("SELECT id_son, score, type FROM collection_collection WHERE id_dad=%s ORDER BY score ASC,id_son", (ccolID, )) ssize += 1 ntree = [] for i in range(0, len(res)): id_son = res[i][0] score = res[i][1] rtype = res[i][2] stack.append(id_son) if i == (len(res) - 1): up = 0 else: up = 1 if i == 0: down = 0 else: down = 1 ntree.insert(0, (id_son, up, down, ccolID, rtype)) tree = tree[0:ssize] + ntree + tree[ssize:len(tree)] return tree except StandardError, e: register_exception() return () def add_col_dad_son(add_dad, add_son, rtype): """Add a son to a collection (dad) add_dad - add to this collection id add_son - add this collection id rtype - either regular or virtual""" try: res = run_sql("SELECT score FROM collection_collection WHERE id_dad=%s ORDER BY score ASC", (add_dad, )) highscore = 0 for score in res: if int(score[0]) > highscore: highscore = int(score[0]) highscore += 1 res = run_sql("INSERT INTO collection_collection(id_dad,id_son,score,type) values(%s,%s,%s,%s)", (add_dad, add_son, highscore, rtype)) return (1, highscore) except StandardError, e: register_exception() return (0, e) def compare_on_val(first, second): """Compare the two values""" return cmp(first[1], second[1]) def get_col_fld(colID=-1, type = '', id_field=''): """Returns either all portalboxes associated with a collection, or based on either colID or language or both. colID - collection id ln - language id""" sql = "SELECT id_field,id_fieldvalue,type,score,score_fieldvalue FROM collection_field_fieldvalue, field WHERE id_field=field.id" params = [] if colID > -1: sql += " AND id_collection=%s" params.append(colID) if id_field: sql += " AND id_field=%s" params.append(id_field) if type: sql += " AND type=%s" params.append(type) sql += " ORDER BY type, score desc, score_fieldvalue desc" res = run_sql(sql, tuple(params)) return res def get_col_pbx(colID=-1, ln='', position = ''): """Returns either all portalboxes associated with a collection, or based on either colID or language or both. colID - collection id ln - language id""" sql = "SELECT id_portalbox, id_collection, ln, score, position, title, body FROM collection_portalbox, portalbox WHERE id_portalbox = portalbox.id" params = [] if colID > -1: sql += " AND id_collection=%s" params.append(colID) if ln: sql += " AND ln=%s" params.append(ln) if position: sql += " AND position=%s" params.append(position) sql += " ORDER BY position, ln, score desc" res = run_sql(sql, tuple(params)) return res def get_col_fmt(colID=-1): """Returns all formats currently associated with a collection, or for one specific collection colID - the id of the collection""" if colID not in [-1, "-1"]: res = run_sql("SELECT id_format, id_collection, code, score FROM collection_format, format WHERE id_format = format.id AND id_collection=%s ORDER BY score desc", (colID, )) else: res = run_sql("SELECT id_format, id_collection, code, score FROM collection_format, format WHERE id_format = format.id ORDER BY score desc") return res def get_col_rnk(colID, ln): """ Returns a list of the rank methods the given collection is attached to colID - id from collection""" try: res1 = dict(run_sql("SELECT id_rnkMETHOD, '' FROM collection_rnkMETHOD WHERE id_collection=%s", (colID, ))) res2 = get_def_name('', "rnkMETHOD") result = filter(lambda x: res1.has_key(x[0]), res2) return result except StandardError, e: return () def get_pbx(): """Returns all portalboxes""" res = run_sql("SELECT id, title, body FROM portalbox ORDER by title,body") return res def get_fld_value(fldvID = ''): """Returns fieldvalue""" sql = "SELECT id, name, value FROM fieldvalue" params = [] if fldvID: sql += " WHERE id=%s" params.append(fldvID) sql += " ORDER BY name" res = run_sql(sql, tuple(params)) return res def get_pbx_pos(): """Returns a list of all the positions for a portalbox""" position = {} position["rt"] = "Right Top" position["lt"] = "Left Top" position["te"] = "Title Epilog" position["tp"] = "Title Prolog" position["ne"] = "Narrow by coll epilog" position["np"] = "Narrow by coll prolog" return position def get_sort_nametypes(): """Return a list of the various translationnames for the fields""" type = {} type['soo'] = 'Sort options' type['seo'] = 'Search options' type['sew'] = 'Search within' return type def get_fmt_nametypes(): """Return a list of the various translationnames for the output formats""" type = [] type.append(('ln', 'Long name')) return type def get_fld_nametypes(): """Return a list of the various translationnames for the fields""" type = [] type.append(('ln', 'Long name')) return type def get_col_nametypes(): """Return a list of the various translationnames for the collections""" type = [] type.append(('ln', 'Long name')) return type def find_last(tree, start_son): """Find the previous collection in the tree with the same father as start_son""" id_dad = tree[start_son][3] while start_son > 0: start_son -= 1 if tree[start_son][3] == id_dad: return start_son def find_next(tree, start_son): """Find the next collection in the tree with the same father as start_son""" id_dad = tree[start_son][3] while start_son < len(tree): start_son += 1 if tree[start_son][3] == id_dad: return start_son def remove_col_subcol(id_son, id_dad, type): """Remove a collection as a son of another collection in the tree, if collection isn't used elsewhere in the tree, remove all registered sons of the id_son. id_son - collection id of son to remove id_dad - the id of the dad""" try: if id_son != id_dad: tree = get_col_tree(id_son) run_sql("DELETE FROM collection_collection WHERE id_son=%s and id_dad=%s", (id_son, id_dad)) else: tree = get_col_tree(id_son, type) run_sql("DELETE FROM collection_collection WHERE id_son=%s and id_dad=%s and type=%s", (id_son, id_dad, type)) if not run_sql("SELECT id_dad,id_son,type,score from collection_collection WHERE id_son=%s and type=%s", (id_son, type)): for (id, up, down, dad, rtype) in tree: run_sql("DELETE FROM collection_collection WHERE id_son=%s and id_dad=%s", (id, dad)) return (1, "") except StandardError, e: return (0, e) def check_col(add_dad, add_son): """Check if the collection can be placed as a son of the dad without causing loops. add_dad - collection id add_son - collection id""" try: stack = [add_dad] res = run_sql("SELECT id_dad FROM collection_collection WHERE id_dad=%s AND id_son=%s", (add_dad, add_son)) if res: raise StandardError while len(stack) > 0: colID = stack.pop() res = run_sql("SELECT id_dad FROM collection_collection WHERE id_son=%s", (colID, )) for id in res: if int(id[0]) == int(add_son): # raise StandardError # this was the original but it didnt work return(0) else: stack.append(id[0]) return (1, "") except StandardError, e: return (0, e) def attach_rnk_col(colID, rnkID): """attach rank method to collection rnkID - id from rnkMETHOD table colID - id of collection, as in collection table """ try: res = run_sql("INSERT INTO collection_rnkMETHOD(id_collection, id_rnkMETHOD) values (%s,%s)", (colID, rnkID)) return (1, "") except StandardError, e: register_exception() return (0, e) def detach_rnk_col(colID, rnkID): """detach rank method from collection rnkID - id from rnkMETHOD table colID - id of collection, as in collection table """ try: res = run_sql("DELETE FROM collection_rnkMETHOD WHERE id_collection=%s AND id_rnkMETHOD=%s", (colID, rnkID)) return (1, "") except StandardError, e: register_exception() return (0, e) def switch_col_treescore(col_1, col_2): try: res1 = run_sql("SELECT score FROM collection_collection WHERE id_dad=%s and id_son=%s", (col_1[3], col_1[0])) res2 = run_sql("SELECT score FROM collection_collection WHERE id_dad=%s and id_son=%s", (col_2[3], col_2[0])) res = run_sql("UPDATE collection_collection SET score=%s WHERE id_dad=%s and id_son=%s", (res2[0][0], col_1[3], col_1[0])) res = run_sql("UPDATE collection_collection SET score=%s WHERE id_dad=%s and id_son=%s", (res1[0][0], col_2[3], col_2[0])) return (1, "") except StandardError, e: register_exception() return (0, e) def move_col_tree(col_from, col_to, move_to_rtype=''): """Move a collection from one point in the tree to another. becomes a son of the endpoint. col_from - move this collection from current point col_to - and set it as a son of this collection. move_to_rtype - either virtual or regular collection""" try: res = run_sql("SELECT score FROM collection_collection WHERE id_dad=%s ORDER BY score asc", (col_to[0], )) highscore = 0 for score in res: if int(score[0]) > highscore: highscore = int(score[0]) highscore += 1 if not move_to_rtype: move_to_rtype = col_from[4] res = run_sql("DELETE FROM collection_collection WHERE id_son=%s and id_dad=%s", (col_from[0], col_from[3])) res = run_sql("INSERT INTO collection_collection(id_dad,id_son,score,type) values(%s,%s,%s,%s)", (col_to[0], col_from[0], highscore, move_to_rtype)) return (1, "") except StandardError, e: register_exception() return (0, e) def remove_pbx(colID, pbxID, ln): """Removes a portalbox from the collection given. colID - the collection the format is connected to pbxID - the portalbox which should be removed from the collection. ln - the language of the portalbox to be removed""" try: res = run_sql("DELETE FROM collection_portalbox WHERE id_collection=%s AND id_portalbox=%s AND ln=%s", (colID, pbxID, ln)) return (1, "") except StandardError, e: register_exception() return (0, e) def remove_fmt(colID, fmtID): """Removes a format from the collection given. colID - the collection the format is connected to fmtID - the format which should be removed from the collection.""" try: res = run_sql("DELETE FROM collection_format WHERE id_collection=%s AND id_format=%s", (colID, fmtID)) return (1, "") except StandardError, e: register_exception() return (0, e) def remove_fld(colID, fldID, fldvID=''): """Removes a field from the collection given. colID - the collection the format is connected to fldID - the field which should be removed from the collection.""" try: sql = "DELETE FROM collection_field_fieldvalue WHERE id_collection=%s AND id_field=%s" params = [colID, fldID] if fldvID: if fldvID != "None": sql += " AND id_fieldvalue=%s" params.append(fldvID) else: sql += " AND id_fieldvalue is NULL" res = run_sql(sql, tuple(params)) return (1, "") except StandardError, e: register_exception() return (0, e) def delete_fldv(fldvID): """Deletes all data for the given fieldvalue fldvID - delete all data in the tables associated with fieldvalue and this id""" try: res = run_sql("DELETE FROM collection_field_fieldvalue WHERE id_fieldvalue=%s", (fldvID, )) res = run_sql("DELETE FROM fieldvalue WHERE id=%s", (fldvID, )) return (1, "") except StandardError, e: register_exception() return (0, e) def delete_pbx(pbxID): """Deletes all data for the given portalbox pbxID - delete all data in the tables associated with portalbox and this id """ try: res = run_sql("DELETE FROM collection_portalbox WHERE id_portalbox=%s", (pbxID, )) res = run_sql("DELETE FROM portalbox WHERE id=%s", (pbxID, )) return (1, "") except StandardError, e: register_exception() return (0, e) def delete_fmt(fmtID): """Deletes all data for the given format fmtID - delete all data in the tables associated with format and this id """ try: res = run_sql("DELETE FROM format WHERE id=%s", (fmtID, )) res = run_sql("DELETE FROM collection_format WHERE id_format=%s", (fmtID, )) res = run_sql("DELETE FROM formatname WHERE id_format=%s", (fmtID, )) return (1, "") except StandardError, e: register_exception() return (0, e) def delete_col(colID): """Deletes all data for the given collection colID - delete all data in the tables associated with collection and this id """ try: res = run_sql("DELETE FROM collection WHERE id=%s", (colID, )) res = run_sql("DELETE FROM collectionname WHERE id_collection=%s", (colID, )) res = run_sql("DELETE FROM collection_rnkMETHOD WHERE id_collection=%s", (colID, )) res = run_sql("DELETE FROM collection_collection WHERE id_dad=%s", (colID, )) res = run_sql("DELETE FROM collection_collection WHERE id_son=%s", (colID, )) res = run_sql("DELETE FROM collection_portalbox WHERE id_collection=%s", (colID, )) res = run_sql("DELETE FROM collection_format WHERE id_collection=%s", (colID, )) res = run_sql("DELETE FROM collection_field_fieldvalue WHERE id_collection=%s", (colID, )) return (1, "") except StandardError, e: register_exception() return (0, e) def add_fmt(code, name, rtype): """Add a new output format. Returns the id of the format. code - the code for the format, max 6 chars. name - the default name for the default language of the format. rtype - the default nametype""" try: res = run_sql("INSERT INTO format (code, name) values (%s,%s)", (code, name)) fmtID = run_sql("SELECT id FROM format WHERE code=%s", (code,)) res = run_sql("INSERT INTO formatname(id_format, type, ln, value) VALUES (%s,%s,%s,%s)", (fmtID[0][0], rtype, CFG_SITE_LANG, name)) return (1, fmtID) except StandardError, e: register_exception() return (0, e) def update_fldv(fldvID, name, value): """Modify existing fieldvalue fldvID - id of fieldvalue to modify value - the value of the fieldvalue name - the name of the fieldvalue.""" try: res = run_sql("UPDATE fieldvalue set name=%s where id=%s", (name, fldvID)) res = run_sql("UPDATE fieldvalue set value=%s where id=%s", (value, fldvID)) return (1, "") except StandardError, e: register_exception() return (0, e) def add_fldv(name, value): """Add a new fieldvalue, returns id of fieldvalue value - the value of the fieldvalue name - the name of the fieldvalue.""" try: res = run_sql("SELECT id FROM fieldvalue WHERE name=%s and value=%s", (name, value)) if not res: res = run_sql("INSERT INTO fieldvalue (name, value) values (%s,%s)", (name, value)) res = run_sql("SELECT id FROM fieldvalue WHERE name=%s and value=%s", (name, value)) if res: return (1, res[0][0]) else: raise StandardError except StandardError, e: register_exception() return (0, e) def add_pbx(title, body): try: res = run_sql("INSERT INTO portalbox (title, body) values (%s,%s)", (title, body)) res = run_sql("SELECT id FROM portalbox WHERE title=%s AND body=%s", (title, body)) if res: return (1, res[0][0]) else: raise StandardError except StandardError, e: register_exception() return (0, e) def add_col(colNAME, dbquery=None): """Adds a new collection to collection table colNAME - the default name for the collection, saved to collection and collectionname dbquery - query related to the collection""" # BTW, sometimes '' are passed instead of None, so change them to None if not dbquery: dbquery = None try: rtype = get_col_nametypes()[0][0] colID = run_sql("SELECT id FROM collection WHERE id=1") if colID: res = run_sql("INSERT INTO collection (name,dbquery) VALUES (%s,%s)", (colNAME,dbquery)) else: res = run_sql("INSERT INTO collection (id,name,dbquery) VALUES (1,%s,%s)", (colNAME,dbquery)) colID = run_sql("SELECT id FROM collection WHERE name=%s", (colNAME,)) res = run_sql("INSERT INTO collectionname(id_collection, type, ln, value) VALUES (%s,%s,%s,%s)", (colID[0][0], rtype, CFG_SITE_LANG, colNAME)) if colID: return (1, colID[0][0]) else: raise StandardError except StandardError, e: register_exception() return (0, e) def add_col_pbx(colID, pbxID, ln, position, score=''): """add a portalbox to the collection. colID - the id of the collection involved pbxID - the portalbox to add ln - which language the portalbox is for score - decides which portalbox is the most important position - position on page the portalbox should appear.""" try: if score: res = run_sql("INSERT INTO collection_portalbox(id_portalbox, id_collection, ln, score, position) values (%s,%s,'%s',%s,%s)", (pbxID, colID, ln, score, position)) else: res = run_sql("SELECT score FROM collection_portalbox WHERE id_collection=%s and ln=%s and position=%s ORDER BY score desc, ln, position", (colID, ln, position)) if res: score = int(res[0][0]) else: score = 0 res = run_sql("INSERT INTO collection_portalbox(id_portalbox, id_collection, ln, score, position) values (%s,%s,%s,%s,%s)", (pbxID, colID, ln, (score + 1), position)) return (1, "") except StandardError, e: register_exception() return (0, e) def add_col_fmt(colID, fmtID, score=''): """Add a output format to the collection. colID - the id of the collection involved fmtID - the id of the format. score - the score of the format, decides sorting, if not given, place the format on top""" try: if score: res = run_sql("INSERT INTO collection_format(id_format, id_collection, score) values (%s,%s,%s)", (fmtID, colID, score)) else: res = run_sql("SELECT score FROM collection_format WHERE id_collection=%s ORDER BY score desc", (colID, )) if res: score = int(res[0][0]) else: score = 0 res = run_sql("INSERT INTO collection_format(id_format, id_collection, score) values (%s,%s,%s)", (fmtID, colID, (score + 1))) return (1, "") except StandardError, e: register_exception() return (0, e) def add_col_fld(colID, fldID, type, fldvID=''): """Add a sort/search/field to the collection. colID - the id of the collection involved fldID - the id of the field. fldvID - the id of the fieldvalue. type - which type, seo, sew... score - the score of the format, decides sorting, if not given, place the format on top""" try: if fldvID and fldvID not in [-1, "-1"]: run_sql("DELETE FROM collection_field_fieldvalue WHERE id_collection=%s AND id_field=%s and type=%s and id_fieldvalue is NULL", (colID, fldID, type)) res = run_sql("SELECT score FROM collection_field_fieldvalue WHERE id_collection=%s AND id_field=%s and type=%s ORDER BY score desc", (colID, fldID, type)) if res: score = int(res[0][0]) res = run_sql("SELECT score_fieldvalue FROM collection_field_fieldvalue WHERE id_collection=%s AND id_field=%s and type=%s ORDER BY score_fieldvalue desc", (colID, fldID, type)) else: res = run_sql("SELECT score FROM collection_field_fieldvalue WHERE id_collection=%s and type=%s ORDER BY score desc", (colID, type)) if res: score = int(res[0][0]) + 1 else: score = 1 res = run_sql("SELECT id_collection,id_field,id_fieldvalue,type,score,score_fieldvalue FROM collection_field_fieldvalue where id_field=%s and id_collection=%s and type=%s and id_fieldvalue=%s", (fldID, colID, type, fldvID)) if not res: run_sql("UPDATE collection_field_fieldvalue SET score_fieldvalue=score_fieldvalue+1 WHERE id_field=%s AND id_collection=%s and type=%s", (fldID, colID, type)) res = run_sql("INSERT INTO collection_field_fieldvalue(id_field, id_fieldvalue, id_collection, type, score, score_fieldvalue) values (%s,%s,%s,%s,%s,%s)", (fldID, fldvID, colID, type, score, 1)) else: return (0, (1, "Already exists")) else: res = run_sql("SELECT id_collection,id_field,id_fieldvalue,type,score,score_fieldvalue FROM collection_field_fieldvalue WHERE id_collection=%s AND type=%s and id_field=%s and id_fieldvalue is NULL", (colID, type, fldID)) if res: return (0, (1, "Already exists")) else: run_sql("UPDATE collection_field_fieldvalue SET score=score+1") res = run_sql("INSERT INTO collection_field_fieldvalue(id_field, id_collection, type, score,score_fieldvalue) values (%s,%s,%s,%s, 0)", (fldID, colID, type, 1)) return (1, "") except StandardError, e: register_exception() return (0, e) def modify_dbquery(colID, dbquery=None): """Modify the dbquery of an collection. colID - the id of the collection involved dbquery - the new dbquery""" # BTW, sometimes '' is passed instead of None, so change it to None if not dbquery: dbquery = None try: res = run_sql("UPDATE collection SET dbquery=%s WHERE id=%s", (dbquery, colID)) return (1, "") except StandardError, e: register_exception() return (0, e) def modify_pbx(colID, pbxID, sel_ln, score='', position='', title='', body=''): """Modify a portalbox colID - the id of the collection involved pbxID - the id of the portalbox that should be modified sel_ln - the language of the portalbox that should be modified title - the title body - the content score - if several portalboxes in one position, who should appear on top. position - position on page""" try: if title: res = run_sql("UPDATE portalbox SET title=%s WHERE id=%s", (title, pbxID)) if body: res = run_sql("UPDATE portalbox SET body=%s WHERE id=%s", (body, pbxID)) if score: res = run_sql("UPDATE collection_portalbox SET score=%s WHERE id_collection=%s and id_portalbox=%s and ln=%s", (score, colID, pbxID, sel_ln)) if position: res = run_sql("UPDATE collection_portalbox SET position=%s WHERE id_collection=%s and id_portalbox=%s and ln=%s", (position, colID, pbxID, sel_ln)) return (1, "") except Exception, e: register_exception() return (0, e) def switch_fld_score(colID, id_1, id_2): """Switch the scores of id_1 and id_2 in collection_field_fieldvalue colID - collection the id_1 or id_2 is connected to id_1/id_2 - id field from tables like format..portalbox... table - name of the table""" try: res1 = run_sql("SELECT score FROM collection_field_fieldvalue WHERE id_collection=%s and id_field=%s", (colID, id_1)) res2 = run_sql("SELECT score FROM collection_field_fieldvalue WHERE id_collection=%s and id_field=%s", (colID, id_2)) if res1[0][0] == res2[0][0]: return (0, (1, "Cannot rearrange the selected fields, either rearrange by name or use the mySQL client to fix the problem.")) else: res = run_sql("UPDATE collection_field_fieldvalue SET score=%s WHERE id_collection=%s and id_field=%s", (res2[0][0], colID, id_1)) res = run_sql("UPDATE collection_field_fieldvalue SET score=%s WHERE id_collection=%s and id_field=%s", (res1[0][0], colID, id_2)) return (1, "") except StandardError, e: register_exception() return (0, e) def switch_fld_value_score(colID, id_1, fldvID_1, fldvID_2): """Switch the scores of two field_value colID - collection the id_1 or id_2 is connected to id_1/id_2 - id field from tables like format..portalbox... table - name of the table""" try: res1 = run_sql("SELECT score_fieldvalue FROM collection_field_fieldvalue WHERE id_collection=%s and id_field=%s and id_fieldvalue=%s", (colID, id_1, fldvID_1)) res2 = run_sql("SELECT score_fieldvalue FROM collection_field_fieldvalue WHERE id_collection=%s and id_field=%s and id_fieldvalue=%s", (colID, id_1, fldvID_2)) if res1[0][0] == res2[0][0]: return (0, (1, "Cannot rearrange the selected fields, either rearrange by name or use the mySQL client to fix the problem.")) else: res = run_sql("UPDATE collection_field_fieldvalue SET score_fieldvalue=%s WHERE id_collection=%s and id_field=%s and id_fieldvalue=%s", (res2[0][0], colID, id_1, fldvID_1)) res = run_sql("UPDATE collection_field_fieldvalue SET score_fieldvalue=%s WHERE id_collection=%s and id_field=%s and id_fieldvalue=%s", (res1[0][0], colID, id_1, fldvID_2)) return (1, "") except Exception, e: register_exception() return (0, e) def switch_pbx_score(colID, id_1, id_2, sel_ln): """Switch the scores of id_1 and id_2 in the table given by the argument. colID - collection the id_1 or id_2 is connected to id_1/id_2 - id field from tables like format..portalbox... table - name of the table""" try: res1 = run_sql("SELECT score FROM collection_portalbox WHERE id_collection=%s and id_portalbox=%s and ln=%s", (colID, id_1, sel_ln)) res2 = run_sql("SELECT score FROM collection_portalbox WHERE id_collection=%s and id_portalbox=%s and ln=%s", (colID, id_2, sel_ln)) if res1[0][0] == res2[0][0]: return (0, (1, "Cannot rearrange the selected fields, either rearrange by name or use the mySQL client to fix the problem.")) res = run_sql("UPDATE collection_portalbox SET score=%s WHERE id_collection=%s and id_portalbox=%s and ln=%s", (res2[0][0], colID, id_1, sel_ln)) res = run_sql("UPDATE collection_portalbox SET score=%s WHERE id_collection=%s and id_portalbox=%s and ln=%s", (res1[0][0], colID, id_2, sel_ln)) return (1, "") except Exception, e: register_exception() return (0, e) def switch_score(colID, id_1, id_2, table): """Switch the scores of id_1 and id_2 in the table given by the argument. colID - collection the id_1 or id_2 is connected to id_1/id_2 - id field from tables like format..portalbox... table - name of the table""" try: res1 = run_sql("SELECT score FROM collection_%s WHERE id_collection=%%s and id_%s=%%s" % (table, table), (colID, id_1)) res2 = run_sql("SELECT score FROM collection_%s WHERE id_collection=%%s and id_%s=%%s" % (table, table), (colID, id_2)) if res1[0][0] == res2[0][0]: return (0, (1, "Cannot rearrange the selected fields, either rearrange by name or use the mySQL client to fix the problem.")) res = run_sql("UPDATE collection_%s SET score=%%s WHERE id_collection=%%s and id_%s=%%s" % (table, table), (res2[0][0], colID, id_1)) res = run_sql("UPDATE collection_%s SET score=%%s WHERE id_collection=%%s and id_%s=%%s" % (table, table), (res1[0][0], colID, id_2)) return (1, "") except Exception, e: register_exception() return (0, e) def get_detailed_page_tabs(colID=None, recID=None, ln=CFG_SITE_LANG): """ Returns the complete list of tabs to be displayed in the detailed record pages. Returned structured is a dict with - key : last component of the url that leads to detailed record tab: http:www.../record/74/key - values: a dictionary with the following keys: - label: *string* label to be printed as tab (Not localized here) - visible: *boolean* if False, tab should not be shown - enabled: *boolean* if True, tab should be disabled - order: *int* position of the tab in the list of tabs - ln: language of the tab labels returns dict """ _ = gettext_set_language(ln) tabs = {'metadata' : {'label': _('Information'), 'visible': False, 'enabled': True, 'order': 1}, 'references': {'label': _('References'), 'visible': False, 'enabled': True, 'order': 2}, 'citations' : {'label': _('Citations'), 'visible': False, 'enabled': True, 'order': 3}, 'keywords' : {'label': _('Keywords'), 'visible': False, 'enabled': True, 'order': 4}, 'comments' : {'label': _('Discussion'), 'visible': False, 'enabled': True, 'order': 5}, 'usage' : {'label': _('Usage statistics'), 'visible': False, 'enabled': True, 'order': 6}, - 'files' : {'label': _('Fulltext'), 'visible': False, 'enabled': True, 'order': 7}, + 'files' : {'label': _('Files'), 'visible': False, 'enabled': True, 'order': 7}, 'plots' : {'label': _('Plots'), 'visible': False, 'enabled': True, 'order': 8}, 'holdings' : {'label': _('Holdings'), 'visible': False, 'enabled': True, 'order': 9}, } res = run_sql("SELECT tabs FROM collectiondetailedrecordpagetabs " + \ "WHERE id_collection=%s", (colID, )) if len(res) > 0: tabs_state = res[0][0].split(';') for tab_state in tabs_state: if tabs.has_key(tab_state): tabs[tab_state]['visible'] = True; else: # no preference set for this collection. # assume all tabs are displayed for key in tabs.keys(): tabs[key]['visible'] = True if not CFG_WEBCOMMENT_ALLOW_COMMENTS and \ not CFG_WEBCOMMENT_ALLOW_REVIEWS: tabs['comments']['visible'] = False tabs['comments']['enabled'] = False if recID is not None: # Disable references if no references found #bfo = BibFormatObject(recID) #if bfe_references.format_element(bfo, '', '') == '': # tabs['references']['enabled'] = False ## FIXME: the above was commented out because bfe_references ## may be too slow. And we do not really need this anyway ## because we can disable tabs in WebSearch Admin on a ## collection-by-collection basis. If we need this, then we ## should probably call bfo.fields('999') here that should be ## much faster than calling bfe_references. # Disable citations if not citations found #if len(get_cited_by(recID)) == 0: # tabs['citations']['enabled'] = False ## FIXME: the above was commented out because get_cited_by() ## may be too slow. And we do not really need this anyway ## because we can disable tags in WebSearch Admin on a ## collection-by-collection basis. - # Disable fulltext if no file found + # Disable Files tab if no file found # FIXME: check non-Plot type if not CFG_INSPIRE_SITE: brd = BibRecDocs(recID) if len(brd.list_bibdocs()) == 0: tabs['files']['enabled'] = False #Disable holdings tab if collection != Books collection = run_sql("""select name from collection where id=%s""", (colID, )) if collection[0][0] != 'Books': tabs['holdings']['enabled'] = False # Disable Plots tab if no docfile of doctype Plot found brd = BibRecDocs(recID) if len(brd.list_bibdocs('Plot')) == 0: tabs['plots']['enabled'] = False tabs[''] = tabs['metadata'] del tabs['metadata'] return tabs diff --git a/modules/webstyle/doc/admin/webstyle-admin-guide.webdoc b/modules/webstyle/doc/admin/webstyle-admin-guide.webdoc index 4e8442a49..690b05cc6 100644 --- a/modules/webstyle/doc/admin/webstyle-admin-guide.webdoc +++ b/modules/webstyle/doc/admin/webstyle-admin-guide.webdoc @@ -1,516 +1,516 @@ ## -*- mode: html; coding: utf-8; -*- ## This file is part of Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 CERN. ## ## Invenio is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2 of the ## License, or (at your option) any later version. ## ## Invenio 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 ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.

Contents

1. Overview

This document describes how to change the look and feel of your CDS Invenio installation.

1.1 CSS Style Sheet and Images

The most obvious modification you may want to do is the modification of CSS style sheet. You may also customize default images.

1.2 HTML Page Layout

The customization of the general page look and feel is currently different depending on whether you customize HTML-like static pages or dynamic Python pages.

Dynamic HTML pages are used to build the 'interactive' parts of the website, such as the search and browse pages, as well as the admin pages. The content of these pages is defined at run time, depending on the users parameters. You can modify them to provide a totally different experience to your users when browsing . Most probably, you will only want to customize 'webstyle_templates.py', which define the headers and footer of a page.

Static HTML pages are used for basic pages that do not embed dynamic content, such as this guide. They help reducing the load of the server and speed up pages serving. As you will see, even HTML static pages can still contain some values defined at run time, but these are reduced to the minimum compared to dynamic pages. Most probably you will not want to modify these pages, since the small amount of dynamic content they have allow these pages to inherit from the customizations you have made elsewhere, such as in the CSS, and the page header and footer.

1.2.1 Layout of HTML Static Pages

Static HTML pages are all located in the /opt/invenio/lib/webdoc/ installation directory. These files are organized in 3 directories:

  • help: Help pages available to users of your website
  • admin: Mostly guides for admin users
  • hacking: Mostly guides for administrators and developers

These directories do not contain the .html files, but .webdoc files. These 'WebDoc' files are basically HTML with the following main differences:

  • They only contain the body of your page (only content of the <body> tag)
  • You can make use of special tags such as <CFG_SITE_URL> and <CFG_SITE_SUPPORT_EMAIL>, that will be replaced by and , the values that you should have configured in your config.py file.
  • You can internationalize the content. For example:
     <lang>
         <en>Book</en>
         <fr>Livre</fr>
         <de>Buch</de>
     </lang>
     
    will be replaced by "Book" if the user has chosen to display the English version of your site, "Livre" in French or "Buch" in German.

Read the WebDoc syntax guide to learn more about details of the WebDoc syntax.

The advantage of not using raw HTML for these static pages is that they can for example reuse the header and footer that you have defined for dynamic pages, and make use of the variables you have defined in your invenio.conf file. In that way you should not need to adapt them to your needs: they will adapt themselves to your needs.

Any modification should be immediatly visible when looking at the pages from the web: the pages are built "dynamically" and then cached. If you want to force the cache of the pages, use the WebDoc CLI (type /opt/invenio/bin/webdoc --help to learn more about it).

1.2.2 Layout of Python Dynamic Pages

The dynamic Python-powered pages can be customized by making use of Invenio templating system that uses a notion of a template skin. How this works?

When you edit invenio-local.conf during installation or later during runtime (when during runtime, you have to run inveniocfg --update-config-py after editing the conf file), you may choose to use your own templates instead of the provided default ones by editing CFG_WEBSTYLE_TEMPLATE_SKIN variable. Let us say you put ithaca there in order to use your own ithaca style. Now, when you start Apache, then instead of Invenio's usual template files such as webbasket_templates.py the system will look for file named webbasket_templates_ithaca.py and will load the template functions from there instead, provided that they exist. (Otherwise it would fall back to the default ones.)

How do you create such an ithaca style templates file? We do not use one of many existing templating frameworks in Python but a very simple programmer-friendly templating system that enables you to use the full power of Python to inherit from the default templates the output generating functions you want to reuse and to write anew only the functions you would like to modify.

Let's show an example of how to modify the page footer. Create a file named webstyle_templates_ithaca.py with the following content:

 from invenio.config import CFG_SITE_LANG
 from invenio.webstyle_templates import Template as DefaultTemplate
 
 class Template(DefaultTemplate):
     """Ithaca style templates."""
 
     def tmpl_pagefooter(self, req=None, ln=CFG_SITE_LANG, lastupdated=None,
                         pagefooteradd=""):
         """
         Ithaca style page footer.  See the default function for
         the meaning of parameters.
         """
         out = ""
         out += """<hr>This site has no footer.
                   </body>
                   </html>"""
         return out
 
 

After the file was created, restart Apache and lo, your new ithaca style footer will be seen in action.

(A side comment: note that tmpl_page_footer() is an ideal place to put any local code you may want to execute at the end of web request processing when the main page content was just served to the user. As an example, if you are using Google Analytics, you may want to put just after the above out = "" statement your GA script code:

         [...]
         out += """<script src="http://www.google-analytics.com/urchin.js"
                           type="text/javascript">
                   </script>
                   <script type="text/javascript">
                           _uacct = "UA-1234567-8";
                           urchinTracker();
                   </script>"""
         [...]
 
End of the side comment.)

Some further remarks on this templating system:

  • We have observed that in practice the HTML page designers were ofter Python programmers, therefore we have adopted a programmer-friendly templating system.
  • You have to know a bit of Python in order to use it. If you don't know Python, do not worry, because you can basically copy and paste the original tmpl_foo() function definition "as is" into the above-cited example and then you would only modify its HTML snippets. The important thing is to preserve the imports (from invenio.config import CFG_SITE_LANG) as in the original webstyle_templates.py file and to preserve the leading whitespace Pythonic indentation.
  • You do not have to learn "yet another templating language", you can use the full power of Python. The tmpl_foo() functions do not contain any business logic in them, their only purpose is to make the HTML presentation of data supplied to them. But, should you need to carry out a little data transformation, you can do it within the tmpl_foo() function itself, thanks to the full Python power.
  • If you feel like doing so, you can modify all the tmpl_foo() functions across all Invenio modules in a way that will completely change the presentation of elements including their content, position and order on the screen.
  • In practice, it is sufficient to modify the CSS and the webstyle_templates_ithaca.py (and possibly websearch_templates_ithaca.py) files to achieve most important customizations.
  • If you would like to discover which method of which template generate which region on the web page, you can switch on the CFG_WEBSTYLE_INSPECT_TEMPLATES configuration variable in your invenio-local.conf file and rerun sudo -u apache /opt/invenio/bin/inveniocfg --update-config-py. Then, after optionally running bibreformat -a and webcoll -f (if you want to debug search pages) and after having restarted your Apache server (in every case), you will find in your browser that a place-mark has been put next to every region of every page, and that you can hover your mouse pointer over any region of the page in order to discover which module/method/parameters have been used to generate it. This is useful for debugging Python templates and/or for understanding which part of code generates which HTML snippet in the output.
  • We expect to provide possibly more than one skin with the default distribution, so if you have modified Invenio look and feel in an interesting way, please consider donating us your templates.
  • When upgrading from one Invenio release to another, you may find out that the default templates have changed in a way that requires changes to your templates (such as an addition of parameters to cover the new functionality). This is inevitable in any templating system; unless you introduce new parameters, you would not see them being printed. Therefore, if you have modified tmpl_foo() and tmpl_bar(), and you are ugrading to a new release, you may at least briefly check whether the function arguments are the same. A quick check of the body would be helpful too, in case the new release fixed some display-related problems in these functions.

    In order to help you in this task, we provide a tool to check incompatibilities between your customized templates and the default templates.
    This tool can be run before doing a 'make install', therefore giving you a chance to fix your templates before upgrading. Just run 'make check-custom-templates' to get the list of problems found with your templates.

    You can also run this tool any time after the new default templates have been installed, in order to ensure that modifications you have done to your templates are valid. To do so move to your Invenio installation directory, and run:
    $ python /opt/invenio/lib/python/invenio/template.py --check-custom-templates

1.3 Look of Bibliographic References

Bibliographic metadata is formatted using BibFormat. Read the BibFormat documentation for more information.

1.4 Specific Configurations

Note that the search interface pages may be modified to a large extent in the WebSearch Admin Interface by adding HTML portalboxes on various places on the page (right top, before/after page title, before/after narrow by collection boxes, etc).

2. Detailed Record Pages

The web pages displaying the details of a record (such as /record/1) do not only show metadata, but also users' comments and reviews, statistics, etc. This information is organized into tabs.

The content of these tabs can be customized on a collection basis. It is also possible to show/hide tabs depending on the displayed collection.

The detailed record pages also feature a mini panel at the bottom of the page that links to popular functions (The mini panel is only displayed when Information tab is selected).

 
   +--------------Detailed record page-------------+
   |                    header                     |
   |nav. breadcrumb                                |
   |                                               |
   |   .--------------------------------------.    |
-  | .-|Info.|Ref.|Discussion.|Stats.|Fulltext|-.  |
+  | .-|Info.|Ref.|Discussion.|Stats.|Files |-.  |
   | | '--------------------------------------' |  |
   | |                                          |  |
   | |                  content                 |  |
   | |                                          |  |
   | '------------------------------------------'  |
   |                                               |
   | .---------------(Mini Panel)---------------.  |
   | |   Mini    |      Mini     |    Mini      |  |
   | |   File    |     Review    |   Actions    |  |
   | '------------------------------------------'  |
   +-----------------------------------------------+
 

2.1 Available tabs

The following tabs are available: - - + +
Name Description URL (eg. for record '10')
Information Show the formatted metadata of the record /record/10
References Displays the references (bibliography) of the record /record/10/references
Discussion Displays the users' comments and reviews /record/10/comments
/record/10/reviews
Usage Statistics Statistics data and graph about file downloads/views /record/10/usage
FulltextLink(s) to fulltext file(s)
FilesLink(s) to full-text and associated file(s) /record/10/files

The mini panel is only displayed when the Information tab is selected. It is divided into the following sections:

    -
  • Files : quick access to fulltext file(s)
  • +
  • Files : quick access to full-text file(s)
  • Review : quick access to reviewing feature
  • Actions: quick access to several other features

2.2 Showing/Hiding tabs

The WebSearch admin web interface lets you decide for each collection which tabs are to be displayed. Choose a collection to edit in the collection tree and go to its detailed record page options. From there you can select which tabs to show for that collection.

If you want to apply these settings to the subcollections, select Also apply to subcollections before you click on the button.

Note that these settings only affect the tabs, not the content of the tabs: even if a tab is not displayed, it is still possible to access its content using its usual url. This is useful if you decide to completely change the detailed record pages, dropping the tab-metaphor (eg. for a side bar) but still want to access the comments, reviews, etc pages.

Here are some behaviours you should expect when changing the tabs configuration:

  • Given that search results pages always link to /record/10, and given the above comment about accessibility of tabs when they are not displayed, the content of the Information will always be show when clicking on detailed record link in search results, even if the Information tab is set not to be displayed.
  • If you select only 1 tab, none of the tabs will be displayed at the top of the page. This also means that whatever tabs you have selected, you users will always see the content of the 'Information' tabs (see above behaviour).
  • If you select 0 tab, only the content of Information tab is shown. None of the tabs, nor the border that usually surrounds the content of the tabs, nor the minipanel are shown. You should choose this option if you decide to drop the tabs metaphor for the detailed record pages. You can then build your own user interface on this almost blank page (See Customizing content of tabs).
  • Note that Discussion tab will not be shown if you have disabled both the commenting and reviewing features in your installation (CFG_WEBCOMMENT_ALLOW_COMMENTS and CFG_WEBCOMMENT_ALLOW_REVIEWS variable in your config file).

2.3 Customizing content of tabs

The contents of tabs are defined in the following ways:

Information tab
The content of this tab is defined by function tmpl_detailed_record_metadata(..) in websearch_templates.py. By default tmpl_detailed_record_metadata simply returns the result of the formatting of the metadata by BibFormat using the "HD" output format. It can therefore be collection-specific.
References tab
The content of this tab is defined by function tmpl_detailed_record_references(..) in websearch_templates.py. By default tmpl_detailed_record_metadata simply returns the result of the formatting of the metadata by BibFormat using the "HDREF" output format. If the result returned by BibFormat is empty, the tab is disabled (visible, but not clickable). It can therefore be collection-specific.
Discussion tab
The content of this tab is mainly defined by function tmpl_get_comments(..) in webcomment_templates.py. Other functions in this file are also involved in the display.
Usage Statistics tab
The content of this tab is defined by function tmpl_detailed_record_statistics(..) in websearch_templates.py. If the returned content is empty, then the tabs will be disabled (visible, but cannot be clicked).
-
Fulltext tab
+
Files tab
The content of this tab is defined by function tmpl_filelist(..) in websubmit_templates.py.

The content of the mini panel is defined in the following ways:

Files
The content of this section is defined by the output format 'HDFILE'. It can therefore be collection-specific.
Review
The content of this section is defined by function tmpl_mini_review(..) inside webcomment_templates.py
Actions
The content of this section is defined by the output format HDACT. It can therefore be collection-specific.

2.4 Customizing look of tabs

You can customize how tabs look like, as well change the look of the border that surrounds the content of tabs. The mini panel can similarly be customized.

Have a look at the following classes in the CDS css stylesheet:

  • detailedrecordtabs
  • detailedrecordbox
  • detailedrecordminipanel
  • top-left, top-right, bottom-left, bottom-right
  • detailedrecordminipanel{actions,review,file}, detailedrecordshortreminder

Note that a tab might be greyed out (disabled) when its content is empty. This is the case for the References tab (see Customizing -content of tabs -> 'References tab') and the Fulltext tab (if no +content of tabs -> 'References tab') and the Files tab (if no file could be found for the record).

For more advanced modifications (like changing the HTML code of the tabs), you can modify the detailed_record_container(..) and detailed_record_mini_panel(..) functions inside your webstyle_templates.py file.

diff --git a/modules/webstyle/lib/webstyle_templates.py b/modules/webstyle/lib/webstyle_templates.py index c2a117920..b591e0b32 100644 --- a/modules/webstyle/lib/webstyle_templates.py +++ b/modules/webstyle/lib/webstyle_templates.py @@ -1,905 +1,905 @@ ## This file is part of Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 CERN. ## ## Invenio is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2 of the ## License, or (at your option) any later version. ## ## Invenio 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 ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """ WebStyle templates. Customize the look of pages of Invenio """ __revision__ = \ "$Id$" import time import cgi import traceback import urllib import sys import string from invenio.config import \ CFG_SITE_LANG, \ CFG_SITE_NAME, \ CFG_SITE_NAME_INTL, \ CFG_SITE_SUPPORT_EMAIL, \ CFG_SITE_SECURE_URL, \ CFG_SITE_URL, \ CFG_VERSION, \ CFG_WEBSTYLE_INSPECT_TEMPLATES, \ CFG_WEBSTYLE_TEMPLATE_SKIN from invenio.messages import gettext_set_language, language_list_long from invenio.urlutils import make_canonical_urlargd, create_html_link from invenio.dateutils import convert_datecvs_to_datestruct, \ convert_datestruct_to_dategui from invenio.bibformat import format_record from invenio import template websearch_templates = template.load('websearch') class Template: def tmpl_navtrailbox_body(self, ln, title, previous_links, separator, prolog, epilog): """Create navigation trail box body Parameters: - 'ln' *string* - The language to display - 'title' *string* - page title; - 'previous_links' *string* - the trail content from site title until current page (both ends exclusive) - 'prolog' *string* - HTML code to prefix the navtrail item with - 'epilog' *string* - HTML code to suffix the navtrail item with - 'separator' *string* - HTML code that separates two navtrail items Output: - text containing the navtrail Note: returns empty string for Home page. (guessed by title). """ # load the right message language _ = gettext_set_language(ln) out = "" if title == CFG_SITE_NAME_INTL.get(ln, CFG_SITE_NAME): # return empty string for the Home page return out else: out += create_html_link(CFG_SITE_URL, {'ln': ln}, _("Home"), {'class': 'navtrail'}) if previous_links: if out: out += separator out += previous_links if title: if out: out += separator if title == CFG_SITE_NAME_INTL.get(ln, CFG_SITE_NAME): # hide site name, print Home instead out += cgi.escape(_("Home")) else: out += cgi.escape(title) return cgi.escape(prolog) + out + cgi.escape(epilog) def tmpl_page(self, req=None, ln=CFG_SITE_LANG, description="", keywords="", userinfobox="", useractivities_menu="", adminactivities_menu="", navtrailbox="", pageheaderadd="", boxlefttop="", boxlefttopadd="", boxleftbottom="", boxleftbottomadd="", boxrighttop="", boxrighttopadd="", boxrightbottom="", boxrightbottomadd="", titleprologue="", title="", titleepilogue="", body="", lastupdated=None, pagefooteradd="", uid=0, secure_page_p=0, navmenuid="", metaheaderadd="", rssurl=CFG_SITE_URL+"/rss", show_title_p=True, body_css_classes=None): """Creates a complete page Parameters: - 'ln' *string* - The language to display - 'description' *string* - description goes to the metadata in the header of the HTML page - 'keywords' *string* - keywords goes to the metadata in the header of the HTML page - 'userinfobox' *string* - the HTML code for the user information box - 'useractivities_menu' *string* - the HTML code for the user activities menu - 'adminactivities_menu' *string* - the HTML code for the admin activities menu - 'navtrailbox' *string* - the HTML code for the navigation trail box - 'pageheaderadd' *string* - additional page header HTML code - 'boxlefttop' *string* - left-top box HTML code - 'boxlefttopadd' *string* - additional left-top box HTML code - 'boxleftbottom' *string* - left-bottom box HTML code - 'boxleftbottomadd' *string* - additional left-bottom box HTML code - 'boxrighttop' *string* - right-top box HTML code - 'boxrighttopadd' *string* - additional right-top box HTML code - 'boxrightbottom' *string* - right-bottom box HTML code - 'boxrightbottomadd' *string* - additional right-bottom box HTML code - 'title' *string* - the title of the page - 'titleprologue' *string* - what to print before page title - 'titleepilogue' *string* - what to print after page title - 'body' *string* - the body of the page - 'lastupdated' *string* - when the page was last updated - 'uid' *int* - user ID - 'pagefooteradd' *string* - additional page footer HTML code - 'secure_page_p' *int* (0 or 1) - are we to use HTTPS friendly page elements or not? - 'navmenuid' *string* - the id of the navigation item to highlight for this page - 'metaheaderadd' *string* - list of further tags to add to the part of the page - 'rssurl' *string* - the url of the RSS feed for this page - 'show_title_p' *int* (0 or 1) - do we display the page title in the body of the page? - 'body_css_classes' *list* - list of classes to add to the body tag Output: - HTML code of the page """ # load the right message language _ = gettext_set_language(ln) out = self.tmpl_pageheader(req, ln = ln, headertitle = title, description = description, keywords = keywords, metaheaderadd = metaheaderadd, userinfobox = userinfobox, useractivities_menu = useractivities_menu, adminactivities_menu = adminactivities_menu, navtrailbox = navtrailbox, pageheaderadd = pageheaderadd, secure_page_p = secure_page_p, navmenuid=navmenuid, rssurl=rssurl, body_css_classes=body_css_classes) + """
%(boxlefttop)s
%(boxlefttopadd)s
%(boxleftbottomadd)s
%(boxleftbottom)s
%(boxrighttop)s
%(boxrighttopadd)s
%(boxrightbottomadd)s
%(boxrightbottom)s
%(titleprologue)s %(title)s %(titleepilogue)s %(body)s
""" % { 'boxlefttop' : boxlefttop, 'boxlefttopadd' : boxlefttopadd, 'boxleftbottom' : boxleftbottom, 'boxleftbottomadd' : boxleftbottomadd, 'boxrighttop' : boxrighttop, 'boxrighttopadd' : boxrighttopadd, 'boxrightbottom' : boxrightbottom, 'boxrightbottomadd' : boxrightbottomadd, 'titleprologue' : titleprologue, 'title' : (title and show_title_p) and '

' + cgi.escape(title) + '

' or '', 'titleepilogue' : titleepilogue, 'body' : body, } + self.tmpl_pagefooter(req, ln = ln, lastupdated = lastupdated, pagefooteradd = pagefooteradd) return out def tmpl_pageheader(self, req, ln=CFG_SITE_LANG, headertitle="", description="", keywords="", userinfobox="", useractivities_menu="", adminactivities_menu="", navtrailbox="", pageheaderadd="", uid=0, secure_page_p=0, navmenuid="admin", metaheaderadd="", rssurl=CFG_SITE_URL+"/rss", body_css_classes=None): """Creates a page header Parameters: - 'ln' *string* - The language to display - 'headertitle' *string* - the second part of the page HTML title - 'description' *string* - description goes to the metadata in the header of the HTML page - 'keywords' *string* - keywords goes to the metadata in the header of the HTML page - 'userinfobox' *string* - the HTML code for the user information box - 'useractivities_menu' *string* - the HTML code for the user activities menu - 'adminactivities_menu' *string* - the HTML code for the admin activities menu - 'navtrailbox' *string* - the HTML code for the navigation trail box - 'pageheaderadd' *string* - additional page header HTML code - 'uid' *int* - user ID - 'secure_page_p' *int* (0 or 1) - are we to use HTTPS friendly page elements or not? - 'navmenuid' *string* - the id of the navigation item to highlight for this page - 'metaheaderadd' *string* - list of further tags to add to the part of the page - 'rssurl' *string* - the url of the RSS feed for this page - 'body_css_classes' *list* - list of classes to add to the body tag Output: - HTML code of the page headers """ # load the right message language _ = gettext_set_language(ln) if body_css_classes is None: body_css_classes = [] body_css_classes.append(navmenuid) if CFG_WEBSTYLE_INSPECT_TEMPLATES: inspect_templates_message = '''
CFG_WEBSTYLE_INSPECT_TEMPLATES debugging mode is enabled. Please hover your mouse pointer over any region on the page to see which template function generated it.
''' else: inspect_templates_message = "" out = """\ %(headertitle)s - %(sitename)s %(metaheaderadd)s """ % { 'siteurl' : CFG_SITE_URL, 'sitesecureurl' : CFG_SITE_SECURE_URL, 'cssurl' : secure_page_p and CFG_SITE_SECURE_URL or CFG_SITE_URL, 'cssskin' : CFG_WEBSTYLE_TEMPLATE_SKIN != 'default' and '_' + CFG_WEBSTYLE_TEMPLATE_SKIN or '', 'rssurl': rssurl, 'ln' : ln, 'ln_iso_639_a' : ln.split('_', 1)[0], 'langlink': '?ln=' + ln, 'sitename' : CFG_SITE_NAME_INTL.get(ln, CFG_SITE_NAME), 'headertitle' : cgi.escape(headertitle), 'sitesupportemail' : CFG_SITE_SUPPORT_EMAIL, 'description' : cgi.escape(description), 'keywords' : cgi.escape(keywords), 'metaheaderadd' : metaheaderadd, 'userinfobox' : userinfobox, 'navtrailbox' : navtrailbox, 'useractivities': useractivities_menu, 'adminactivities': adminactivities_menu and (' %(adminactivities)s' % \ {'personalize_selected': navmenuid.startswith('admin') and "selected" or "", 'adminactivities': adminactivities_menu}) or ' ', 'pageheaderadd' : pageheaderadd, 'body_css_classes' : body_css_classes and ' class="%s"' % ' '.join(body_css_classes) or '', 'search_selected': navmenuid == 'search' and "selected" or "", 'submit_selected': navmenuid == 'submit' and "selected" or "", 'personalize_selected': navmenuid.startswith('your') and "selected" or "", 'help_selected': navmenuid == 'help' and "selected" or "", 'msg_search' : _("Search"), 'msg_submit' : _("Submit"), 'msg_personalize' : _("Personalize"), 'msg_help' : _("Help"), 'languagebox' : self.tmpl_language_selection_box(req, ln), 'unAPIurl' : cgi.escape('%s/unapi' % CFG_SITE_URL), 'inspect_templates_message' : inspect_templates_message } return out def tmpl_pagefooter(self, req=None, ln=CFG_SITE_LANG, lastupdated=None, pagefooteradd=""): """Creates a page footer Parameters: - 'ln' *string* - The language to display - 'lastupdated' *string* - when the page was last updated - 'pagefooteradd' *string* - additional page footer HTML code Output: - HTML code of the page headers """ # load the right message language _ = gettext_set_language(ln) if lastupdated and lastupdated != '$Date$': if lastupdated.startswith("$Date: ") or \ lastupdated.startswith("$Id: "): lastupdated = convert_datestruct_to_dategui(\ convert_datecvs_to_datestruct(lastupdated), ln=ln) msg_lastupdated = _("Last updated") + ": " + lastupdated else: msg_lastupdated = "" out = """ """ % { 'siteurl' : CFG_SITE_URL, 'sitesecureurl' : CFG_SITE_SECURE_URL, 'ln' : ln, 'langlink': '?ln=' + ln, 'sitename' : CFG_SITE_NAME_INTL.get(ln, CFG_SITE_NAME), 'sitesupportemail' : CFG_SITE_SUPPORT_EMAIL, 'msg_search' : _("Search"), 'msg_submit' : _("Submit"), 'msg_personalize' : _("Personalize"), 'msg_help' : _("Help"), 'msg_poweredby' : _("Powered by"), 'msg_maintainedby' : _("Maintained by"), 'msg_lastupdated' : msg_lastupdated, 'languagebox' : self.tmpl_language_selection_box(req, ln), 'version' : CFG_VERSION, 'pagefooteradd' : pagefooteradd, } return out def tmpl_language_selection_box(self, req, language=CFG_SITE_LANG): """Take URLARGS and LANGUAGE and return textual language selection box for the given page. Parameters: - 'req' - The mod_python request object - 'language' *string* - The selected language """ # load the right message language _ = gettext_set_language(language) # Work on a copy in order not to bork the arguments of the caller argd = {} if req and req.args: argd.update(cgi.parse_qs(req.args)) parts = [] for (lang, lang_namelong) in language_list_long(): if lang == language: parts.append('%s' % lang_namelong) else: # Update the 'ln' argument in the initial request argd['ln'] = lang if req and req.uri: args = urllib.quote(req.uri, '/:?') + make_canonical_urlargd(argd, {}) else: args = "" parts.append(create_html_link(args, {}, lang_namelong, {'class': "langinfo"})) if len(parts) > 1: return _("This site is also available in the following languages:") + \ "
" + '  '.join(parts) else: ## There is only one (or zero?) languages configured, ## so there so need to display language alternatives. return "" def tmpl_error_box(self, ln, title, verbose, req, errors): """Produces an error box. Parameters: - 'title' *string* - The title of the error box - 'ln' *string* - The selected language - 'verbose' *bool* - If lots of information should be displayed - 'req' *object* - the request object - 'errors' list of tuples (error_code, error_message) """ # load the right message language _ = gettext_set_language(ln) info_not_available = _("N/A") if title is None: if errors: title = _("Error") + ': %s' % errors[0][1] else: title = _("Internal Error") browser_s = _("Browser") if req: try: if req.headers_in.has_key('User-Agent'): browser_s += ': ' + req.headers_in['User-Agent'] else: browser_s += ': ' + info_not_available host_s = req.hostname page_s = req.unparsed_uri client_s = req.remote_ip except: # FIXME: bad except browser_s += ': ' + info_not_available host_s = page_s = client_s = info_not_available else: browser_s += ': ' + info_not_available host_s = page_s = client_s = info_not_available error_s = '' sys_error_s = '' traceback_s = '' if verbose >= 1: if sys.exc_info()[0]: sys_error_s = '\n' + _("System Error") + ': %s %s\n' % \ (sys.exc_info()[0], sys.exc_info()[1]) if errors: errs = '' for error_tuple in errors: try: errs += "%s%s : %s\n " % (' '*6, error_tuple[0], error_tuple[1]) except: errs += "%s%s\n" % (' '*6, error_tuple) errs = errs[6:-2] # get rid of trainling ',' error_s = _("Error") + ': %s")' % errs + "\n" else: error_s = _("Error") + ': ' + info_not_available if verbose >= 9: traceback_s = '\n' + _("Traceback") + ': \n%s' % \ string.join(traceback.format_tb(sys.exc_info()[2]), "\n") out = """

%(title)s %(sys1)s %(sys2)s

%(contact)s

 URI: http://%(host)s%(page)s
 %(time_label)s: %(time)s
 %(browser)s
 %(client_label)s: %(client)s
 %(error)s%(sys_error)s%(traceback)s
 
%(send_error_label)s
""" % { 'title' : cgi.escape(title).replace('"', '"'), 'time_label': _("Time"), 'client_label': _("Client"), 'send_error_label': \ _("Please send an error report to the administrator."), 'send_label': _("Send error report"), 'sys1' : cgi.escape(str((sys.exc_info()[0] or ''))).replace('"', '"'), 'sys2' : cgi.escape(str((sys.exc_info()[1] or ''))).replace('"', '"'), 'contact' : \ _("Please contact %s quoting the following information:") % \ ('' + \ CFG_SITE_SUPPORT_EMAIL + ''), 'host' : cgi.escape(host_s), 'page' : cgi.escape(page_s), 'time' : time.strftime("%d/%b/%Y:%H:%M:%S %z"), 'browser' : cgi.escape(browser_s).replace('"', '"'), 'client' : cgi.escape(client_s).replace('"', '"'), 'error' : cgi.escape(error_s).replace('"', '"'), 'traceback' : cgi.escape(traceback_s).replace('"', '"'), 'sys_error' : cgi.escape(sys_error_s).replace('"', '"'), 'siteurl' : CFG_SITE_URL, 'referer' : page_s!=info_not_available and \ ("http://" + host_s + page_s) or \ info_not_available } return out def detailed_record_container_top(self, recid, tabs, ln=CFG_SITE_LANG, show_similar_rec_p=True, creationdate=None, modificationdate=None, show_short_rec_p=True, citationnum=-1, referencenum=-1): """Prints the box displayed in detailed records pages, with tabs at the top. Returns content as it is if the number of tabs for this record is smaller than 2 Parameters: @param recid: int - the id of the displayed record @param tabs: ** - the tabs displayed at the top of the box. @param ln: *string* - the language of the page in which the box is displayed @param show_similar_rec_p: *bool* print 'similar records' link in the box @param creationdate: *string* - the creation date of the displayed record @param modificationdate: *string* - the last modification date of the displayed record @param show_short_rec_p: *boolean* - prints a very short version of the record as reminder. @param citationnum: show (this) number of citations in the citations tab @param referencenum: show (this) number of references in the references tab """ # If no tabs, returns nothing if len(tabs) <= 1: return '' # load the right message language _ = gettext_set_language(ln) # Build the tabs at the top of the page out_tabs = '' if len(tabs) > 1: first_tab = True for (label, url, selected, enabled) in tabs: addnum = "" if (citationnum > -1) and url.count("/citation") == 1: addnum = "(" + str(citationnum) + ")" if (referencenum > -1) and url.count("/references") == 1: addnum = "(" + str(referencenum) + ")" css_class = [] if selected: css_class.append('on') if first_tab: css_class.append('first') first_tab = False if not enabled: css_class.append('disabled') css_class = ' class="%s"' % ' '.join(css_class) if not enabled: out_tabs += '%(label)s %(addnum)s' % \ {'class':css_class, 'label':label, 'addnum':addnum} else: out_tabs += '%(label)s %(addnum)s ' % \ {'class':css_class, 'url':url, 'label':label, 'addnum':addnum} if out_tabs != '': out_tabs = '''
    %s
 
''' % out_tabs # Add the clip icon and the brief record reminder if necessary record_brief = '' if show_short_rec_p: record_brief = format_record(recID=recid, of='hs', ln=ln) record_brief = '''
 
%(record_brief)s
 
''' % {'record_brief': record_brief} # Print the content out = """
%(tabs)s
%(record_brief)s """ % {'tabs':out_tabs, 'record_brief':record_brief} return out def detailed_record_container_bottom(self, recid, tabs, ln=CFG_SITE_LANG, show_similar_rec_p=True, creationdate=None, modificationdate=None, show_short_rec_p=True): """Prints the box displayed in detailed records pages, with tabs at the top. Returns content as it is if the number of tabs for this record is smaller than 2 Parameters: - recid *int* - the id of the displayed record - tabs ** - the tabs displayed at the top of the box. - ln *string* - the language of the page in which the box is displayed - show_similar_rec_p *bool* print 'similar records' link in the box - creationdate *string* - the creation date of the displayed record - modificationdate *string* - the last modification date of the displayed record - show_short_rec_p *boolean* - prints a very short version of the record as reminder. """ # If no tabs, returns nothing if len(tabs) <= 1: return '' # load the right message language _ = gettext_set_language(ln) out = """

 

%(dates)s
%(similar)s

""" % {'similar':create_html_link( websearch_templates.build_search_url(p='recid:%d' % \ recid, rm='wrd', ln=ln), {}, _("Similar records"), {'class': "moreinfo"}), 'dates':creationdate and '
 %(dates)s
' % { 'dates': _("Record created %(x_date_creation)s, last modified %(x_date_modification)s") % \ {'x_date_creation': creationdate, 'x_date_modification': modificationdate}, } or '' } return out def detailed_record_mini_panel(self, recid, ln=CFG_SITE_LANG, format='hd', files='', reviews='', actions=''): """Displays the actions dock at the bottom of the detailed record pages. Parameters: - recid *int* - the id of the displayed record - ln *string* - interface language code - format *string* - the format used to display the record - - files *string* - the small panel representing the fulltext + - files *string* - the small panel representing the attached files - reviews *string* - the small panel representing the reviews - actions *string* - the small panel representing the possible user's action """ # load the right message language _ = gettext_set_language(ln) out = """
%(files)s
%(reviews)s
%(actions)s
""" % { 'siteurl': CFG_SITE_URL, 'ln':ln, 'recid':recid, 'files': files, 'reviews':reviews, 'actions': actions, } return out def tmpl_error_page(self, ln=CFG_SITE_LANG, status="", admin_was_alerted=True): """ Display an error page. - status *string* - the HTTP status. """ _ = gettext_set_language(ln) out = """

%(message)s

%(alerted)s

%(doubts)s

""" % { 'status' : status, 'message' : _("The server encountered an error while dealing with your request."), 'alerted' : admin_was_alerted and _("The system administrators have been alerted.") or '', 'doubts' : _("In case of doubt, please contact %(x_admin_email)s.") % {'x_admin_email' : '%(admin)s' % {'admin' : CFG_SITE_SUPPORT_EMAIL}} } return out