diff --git a/configure.ac b/configure.ac
index 9cce278beb..1d23eca507 100644
--- a/configure.ac
+++ b/configure.ac
@@ -874,6 +874,10 @@ AC_CONFIG_FILES([config.nice \
modules/webmessage/doc/hacking/Makefile \
modules/webmessage/lib/Makefile \
modules/webmessage/web/Makefile \
+ modules/webnews/Makefile \
+ modules/webnews/doc/Makefile \
+ modules/webnews/lib/Makefile \
+ modules/webnews/web/Makefile \
modules/websearch/Makefile \
modules/websearch/bin/Makefile \
modules/websearch/bin/webcoll \
diff --git a/modules/Makefile.am b/modules/Makefile.am
index 0d72e5de03..469ab7c02b 100644
--- a/modules/Makefile.am
+++ b/modules/Makefile.am
@@ -52,6 +52,7 @@ SUBDIRS = bibauthorid \
webjournal \
weblinkback \
webmessage \
+ webnews \
websearch \
websession \
webstat \
diff --git a/modules/miscutil/lib/upgrades/invenio_2013_02_15_webnews_new_db_tables.py b/modules/miscutil/lib/upgrades/invenio_2013_02_15_webnews_new_db_tables.py
new file mode 100644
index 0000000000..bc01d22971
--- /dev/null
+++ b/modules/miscutil/lib/upgrades/invenio_2013_02_15_webnews_new_db_tables.py
@@ -0,0 +1,82 @@
+# -*- coding: utf-8 -*-
+##
+## This file is part of Invenio.
+## Copyright (C) 2012 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.
+
+from invenio.dbquery import run_sql
+
+depends_on = ['invenio_release_1_1_0']
+
+def info():
+ return "New database tables for the WebNews module"
+
+def do_upgrade():
+ query_story = \
+"""DROP TABLE IF EXISTS `nwsSTORY`;
+CREATE TABLE `nwsSTORY` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `title` varchar(256) NOT NULL,
+ `body` text NOT NULL,
+ `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`)
+);"""
+ run_sql(query_story)
+
+ query_tag = \
+"""DROP TABLE IF EXISTS `nwsTAG`;
+CREATE TABLE `nwsTAG` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `tag` varchar(64) NOT NULL,
+ PRIMARY KEY (`id`)
+);"""
+ run_sql(query_tag)
+
+ query_tooltip = \
+"""DROP TABLE IF EXISTS `nwsTOOLTIP`;
+CREATE TABLE `nwsTOOLTIP` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `id_story` int(11) NOT NULL,
+ `body` varchar(512) NOT NULL,
+ `target_element` varchar(256) NOT NULL DEFAULT '',
+ `target_page` varchar(256) NOT NULL DEFAULT '',
+ PRIMARY KEY (`id`),
+ KEY `id_story` (`id_story`),
+ CONSTRAINT `nwsTOOLTIP_ibfk_1` FOREIGN KEY (`id_story`) REFERENCES `nwsSTORY` (`id`)
+);"""
+ run_sql(query_tooltip)
+
+ query_story_tag = \
+"""DROP TABLE IF EXISTS `nwsSTORY_nwsTAG`;
+CREATE TABLE `nwsSTORY_nwsTAG` (
+ `id_story` int(11) NOT NULL,
+ `id_tag` int(11) NOT NULL,
+ PRIMARY KEY (`id_story`,`id_tag`),
+ KEY `id_story` (`id_story`),
+ KEY `id_tag` (`id_tag`),
+ CONSTRAINT `nwsSTORY_nwsTAG_ibfk_1` FOREIGN KEY (`id_story`) REFERENCES `nwsSTORY` (`id`),
+ CONSTRAINT `nwsSTORY_nwsTAG_ibfk_2` FOREIGN KEY (`id_tag`) REFERENCES `nwsTAG` (`id`)
+);"""
+ run_sql(query_story_tag)
+
+def estimate():
+ return 1
+
+def pre_upgrade():
+ pass
+
+def post_upgrade():
+ pass
diff --git a/modules/webnews/Makefile.am b/modules/webnews/Makefile.am
new file mode 100644
index 0000000000..b75d18399a
--- /dev/null
+++ b/modules/webnews/Makefile.am
@@ -0,0 +1,20 @@
+## This file is part of Invenio.
+## Copyright (C) 2005, 2006, 2007, 2008, 2010, 2011 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.
+
+SUBDIRS = lib web doc
+
+CLEANFILES = *~
diff --git a/modules/webnews/doc/Makefile.am b/modules/webnews/doc/Makefile.am
new file mode 100644
index 0000000000..fb4b48b5c1
--- /dev/null
+++ b/modules/webnews/doc/Makefile.am
@@ -0,0 +1,18 @@
+## This file is part of Invenio.
+## Copyright (C) 2005, 2006, 2007, 2008, 2010, 2011 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.
+
+CLEANFILES = *~
diff --git a/modules/webnews/lib/Makefile.am b/modules/webnews/lib/Makefile.am
new file mode 100644
index 0000000000..0059e32654
--- /dev/null
+++ b/modules/webnews/lib/Makefile.am
@@ -0,0 +1,36 @@
+## This file is part of Invenio.
+## Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 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.
+
+pylibdir = $(libdir)/python/invenio
+webdir = $(localstatedir)/www/img
+jsdir = $(localstatedir)/www/js
+
+pylib_DATA = webnews.py \
+ webnews_config.py \
+ webnews_webinterface.py \
+ webnews_dblayer.py \
+ webnews_utils.py
+
+js_DATA = webnews.js
+
+web_DATA = webnews.css
+
+EXTRA_DIST = $(pylib_DATA) \
+ $(js_DATA) \
+ $(web_DATA)
+
+CLEANFILES = *~ *.tmp *.pyc
diff --git a/modules/webnews/lib/webnews.css b/modules/webnews/lib/webnews.css
new file mode 100644
index 0000000000..b6de6eca33
--- /dev/null
+++ b/modules/webnews/lib/webnews.css
@@ -0,0 +1,162 @@
+/***************************************************************************
+* Assume that we want the arrow's size (i.e. side; height in case it's on *
+* the left or right side; width otherwise) to be 16px. Then the border *
+* width for the arrow and its border will be half that dimension, 8px. In *
+* order for the arrow to be right on the tooltip, the arrow border's left *
+* positioning has to be as much as it's size, therefore -16px. The arrow's *
+* left positioning has to be a couple of pixels to the right in order for *
+* the border effect to be visible, therefore -14px. At the same time, in *
+* order for the arrow's point to not overlap with the targeted item, the *
+* tooltip's left margin has to be half the arrow's size (=the arrow's *
+* border width), 8px. The tooltip's padding has to at least as much as the *
+* arrow's left positioning overhead, (-(-16px-(-14px))) 2px in this case. *
+* The arrow's and the arrow border's top positioning can be as much as we *
+* want, and it must be the same for both. *
+* *
+* Desired arrow's size ([height|width]): 16px *
+* Arrow's border-width: 8px (half the arrow's size) *
+* Tooltip's [left|right] margin: 8px (half the arrow's size) *
+* Arrow's [left|right] positioning: -16px & -14px (arrow border and arrow) *
+* Arrow's [top|bottom] positioning: 8px *
+* *
+***************************************************************************/
+
+/* Arrow implementation using traditional elements */
+.ttn {
+ /* Display */
+ position: absolute;
+ display: none;
+ z-index: 9997;
+
+ /* Dimensions */
+ max-width: 250px;
+ min-width: 150px;
+
+ /* Contents */
+ background: #FFFFCC;
+ margin-left: 8px;
+ padding: 5px; /* padding has to be at least 2 */
+ font-size: small;
+
+ /* Border */
+ border: 1px solid #FFCC00;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ -o-border-radius: 5px;
+ border-radius: 5px;
+
+ /* Shadow */
+ -moz-box-shadow: 1px 1px 3px gray;
+ -webkit-box-shadow: 1px 1px 3px gray;
+ -o-box-shadow: 1px 1px 3px gray;
+ box-shadow: 1px 1px 3px gray;
+}
+
+.ttn_arrow {
+ /* Display */
+ position: absolute;
+ left: -14px;
+ top: 8px;
+ z-index: 9999;
+
+ /* Dimensions */
+ height: 0;
+ width: 0;
+
+ /* Border */
+ border-color: transparent #FFFFCC transparent transparent;
+ border-color: rgba(255,255,255,0) #FFFFCC rgba(255,255,255,0) rgba(255,255,255,0);
+ border-style: solid;
+ border-width: 8px;
+}
+
+.ttn_arrow_border {
+ /* Display */
+ position: absolute;
+ left: -16px;
+ top: 8px;
+ z-index: 9998;
+
+ /* Dimensions */
+ height: 0;
+ width: 0;
+
+ /* Border */
+ border-color: transparent #FFCC00 transparent transparent;
+ border-color: rgba(255,255,255,0) #FFCC00 rgba(255,255,255,0) rgba(255,255,255,0);
+ border-style: solid;
+ border-width: 8px;
+}
+
+/* Arrow implementation using the :before and :after pseudo elements */
+.ttn_alt_arrow_box {
+ /* Display */
+ position: absolute;
+ display: none;
+ z-index: 9997;
+
+ /* Dimensions */
+ max-width: 250px;
+ min-width: 150px;
+
+ /* Contents */
+ background: #FFFFCC;
+ margin-left: 6px;
+ padding: 3px;
+
+ /* Border */
+ border: 1px solid #FFCC00;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ -o-border-radius: 5px;
+ border-radius: 5px;
+
+ /* Shadow */
+ -moz-box-shadow: 1px 1px 3px gray;
+ -webkit-box-shadow: 1px 1px 3px gray;
+ -o-box-shadow: 1px 1px 3px gray;
+ box-shadow: 1px 1px 3px gray;
+}
+
+.ttn_alt_arrow_box:after, .ttn_alt_arrow_box:before {
+ right: 100%;
+ border: 1px solid transparent;
+ content: " ";
+ height: 0;
+ width: 0;
+ position: absolute;
+ pointer-events: none;
+}
+
+.ttn_alt_arrow_box:after {
+ border-color: transparent;
+ border-right-color: #FFFFCC;
+ border-width: 6px;
+ top: 13px;
+}
+
+.ttn_alt_arrow_box:before {
+ border-color: transparent;
+ border-right-color: #FFCC00;
+ border-width: 8px;
+ top: 11px;
+}
+
+/* Style for the tooltip's contents */
+.ttn_text {
+ /* Contents */
+ vertical-align: top;
+ text-align: left;
+}
+
+.ttn_actions {
+ /* Contents */
+ vertical-align: bottom;
+ text-align: right;
+}
+
+.ttn_actions_read_more {
+}
+
+.ttn_actions_dismiss {
+}
diff --git a/modules/webnews/lib/webnews.js b/modules/webnews/lib/webnews.js
new file mode 100644
index 0000000000..75c953fcaa
--- /dev/null
+++ b/modules/webnews/lib/webnews.js
@@ -0,0 +1,256 @@
+/******************************************************************************
+* WebNews JavaScript Library
+*
+* Includes functions to create and place the tooltips, and re-place them
+* in case the browser window is resized.
+*
+* TODO: remove magic numbers and colors
+*
+******************************************************************************/
+
+// Tooltips entry function. Create all the tooltips.
+function create_tooltips(data) {
+
+ // Get all the tooltips.
+ var tooltips = data['tooltips'];
+
+ // Only proceed if there are tooltips.
+ if ( tooltips != undefined ) {
+
+ // Get the story id and ln, to be used to create the "Read more" URL.
+ var story_id = data['story_id'];
+ var ln = data['ln'];
+
+ // Keep an array of the tooltip notification and target elements,
+ // to be used to speed up the window resize function later.
+ var tooltips_elements = [];
+
+ // Create each tooltip and get its notification and target elements.
+ for (var i = 0; i < tooltips.length; i++) {
+ tooltip = tooltips[i];
+ tooltip_elements = create_tooltip(tooltip, story_id, ln);
+ tooltips_elements.push(tooltip_elements);
+ }
+
+ /*
+ // To cover most cases, we need to call re_place_tooltip both on page
+ // resize and page scroll. So, let's combine both events usings ".on()"
+ $(window).resize(function() {
+ for (var i = 0; i < tooltips_elements.length; i++) {
+ var tooltip_notification = tooltips_elements[i][0];
+ var tooltip_target = tooltips_elements[i][1];
+ re_place_tooltip(tooltip_notification, tooltip_target);
+ }
+ });
+
+ $(window).scroll(function() {
+ for (var i = 0; i < tooltips_elements.length; i++) {
+ var tooltip_notification = tooltips_elements[i][0];
+ var tooltip_target = tooltips_elements[i][1];
+ re_place_tooltip(tooltip_notification, tooltip_target);
+ }
+ });
+ */
+
+ $(window).on("resize scroll", function() {
+ for (var i = 0; i < tooltips_elements.length; i++) {
+ var tooltip_notification = tooltips_elements[i][0];
+ var tooltip_target = tooltips_elements[i][1];
+ re_place_tooltip(tooltip_notification, tooltip_target);
+ }
+ });
+
+ }
+
+}
+
+function create_tooltip(tooltip, story_id, ln) {
+
+ // Get the tooltip data.
+ var id = tooltip['id'];
+ var target = tooltip['target'];
+ var body = tooltip['body'];
+ var readmore = tooltip['readmore'];
+ var dismiss = tooltip['dismiss'];
+
+ // Create the "Read more" URL.
+ var readmore_url = '/news/story?id=' + story_id + '&ln=' + ln
+
+ // Construct the tooltip html.
+ var tooltip_html = '
\n';
+ tooltip_html += '
' + body + '
\n';
+ tooltip_html += '
\n';
+ // TODO: Do not add the "Read more" label until the /news interface is ready.
+ //tooltip_html += ' ' + readmore + '\n';
+ //tooltip_html += ' | \n';
+ tooltip_html += ' ' + dismiss + '\n';
+ tooltip_html += '
\n';
+
+ // Append the tooltip html to the body.
+ $('body').append(tooltip_html);
+
+ // Create the jquery element selectors for the tooltip notification and target.
+ var tooltip_notification = $("#" + id);
+ var tooltip_target = eval(target);
+
+ // Place and display the tooltip.
+ place_tooltip(tooltip_notification, tooltip_target);
+
+ // Return the tooltip notification and target elements in an array.
+ return [tooltip_notification, tooltip_target];
+}
+
+function place_tooltip(tooltip_notification, tooltip_target) {
+
+ // Only display the tooltip if the tooltip_notification exists
+ // and the tooltip exists and is visible.
+ if ( tooltip_notification.length > 0 && tooltip_target.length > 0 && tooltip_target.is(":visible") ) {
+
+ // First, calculate the top of tooltip_notification:
+ // This comes from tooltip_target's top with some adjustments
+ // in order to place the tooltip in the middle of the tooltip_target.
+ var tooltip_target_height = tooltip_target.outerHeight();
+ var tooltip_target_top = tooltip_target.offset().top;
+ // The distance from the top of the tooltip_notifcation to the
+ // arrow's tip is 16px (half the arrow's size + arrow's top margin)
+ var tooltip_notification_top = tooltip_target_top + ( tooltip_target_height / 2 ) - 16
+ if ( tooltip_notification_top < 0 ) {
+ tooltip_notification_top = 0;
+ }
+
+ // Second, calculate the left of tooltip_notification:
+ // This comes from the sum of tooltip_target's left and width
+ var tooltip_target_left = tooltip_target.offset().left;
+ var tooltip_target_width = tooltip_target.outerWidth();
+ var tooltip_notification_left = tooltip_target_left + tooltip_target_width;
+
+ // However, if tooltip_notification appears to be displayed outside the window,
+ // then we have to place it on the other side of tooltip_target
+ var tooltip_notification_width = tooltip_notification.outerWidth();
+ var window_width = $(window).width();
+ if ( ( tooltip_notification_left + tooltip_notification_width ) > window_width ) {
+ // Place tooltip_notification on the other side, taking into account the arrow's size
+ // The left margin of the tooltip_notification and half the
+ // arrow's size is 16px
+ tooltip_notification_left = tooltip_target_left - tooltip_notification_width - 16;
+ // Why does 4px work perfectly here?
+ tooltip_notification.children("div[class='ttn_arrow']").css("left", (tooltip_notification_width - 4) + "px");
+ tooltip_notification.children("div[class='ttn_arrow']").css("border-color", "transparent transparent transparent #FFFFCC");
+ tooltip_notification.children("div[class='ttn_arrow']").css("border-color", "rgba(255,255,255,0) rgba(255,255,255,0) rgba(255,255,255,0) #FFFFCC");
+ // 2px is 4px - 2px here, since the arrow's border has a 2px offset from the arrow
+ tooltip_notification.children("div[class='ttn_arrow_border']").css("left", "").css("left", (tooltip_notification_width - 2) + "px");
+ tooltip_notification.children("div[class='ttn_arrow_border']").css("border-color", "transparent transparent transparent #FFCC00");
+ tooltip_notification.children("div[class='ttn_arrow_border']").css("border-color", "rgba(255,255,255,0) rgba(255,255,255,0) rgba(255,255,255,0) #FFCC00");
+ tooltip_notification.css("-moz-box-shadow", "-1px 1px 3px gray");
+ tooltip_notification.css("-webkit-box-shadow", "-1px 1px 3px gray");
+ tooltip_notification.css("-o-box-shadow", "-1px 1px 3px gray");
+ tooltip_notification.css("box-shadow", "-1px 1px 3px gray");
+ }
+
+ // Set the final attributes and display tooltip_notification
+ tooltip_notification.css('top', tooltip_notification_top + 'px');
+ tooltip_notification.css('left', tooltip_notification_left + 'px');
+ tooltip_notification.fadeIn();
+ tooltip_notification.find("a[class='ttn_actions_dismiss']").click(function() {
+ $.ajax({
+ url: "/news/dismiss",
+ data: { tooltip_notification_id: tooltip_notification.attr("id") },
+ success: function(data) {
+ if ( data["success"] == 1 ) {
+ tooltip_notification.fadeOut();
+ }
+ },
+ dataType: "json"
+ });
+ });
+
+ }
+
+}
+
+function re_place_tooltip(tooltip_notification, tooltip_target) {
+
+ // Only display the tooltip if the tooltip_notification exists
+ // and the tooltip exists and is visible.
+ if ( tooltip_notification.length > 0 && tooltip_notification.is(":visible") && tooltip_target.length > 0 && tooltip_target.is(":visible") ) {
+
+ // First, calculate the top of tooltip_notification:
+ // This comes from tooltip_target's top with some adjustments
+ // in order to place the tooltip in the middle of the tooltip_target.
+ var tooltip_target_height = tooltip_target.outerHeight();
+ var tooltip_target_top = tooltip_target.offset().top;
+ // The distance from the top of the tooltip_notifcation to the
+ // arrow's tip is 16px (half the arrow's size + arrow's top margin)
+ var tooltip_notification_top = tooltip_target_top + ( tooltip_target_height / 2 ) - 16
+ if ( tooltip_notification_top < 0 ) {
+ tooltip_notification_top = 0;
+ }
+
+ // Second, calculate the left of tooltip_notification:
+ // This comes from the sum of tooltip_target's left and width
+ var tooltip_target_left = tooltip_target.offset().left;
+ var tooltip_target_width = tooltip_target.outerWidth();
+ var tooltip_notification_left = tooltip_target_left + tooltip_target_width;
+
+ // However, if tooltip_notification appears to be displayed outside the window,
+ // then we have to place it on the other side of tooltip_target
+ var tooltip_notification_width = tooltip_notification.outerWidth();
+ var window_width = $(window).width();
+ if ( ( tooltip_notification_left + tooltip_notification_width ) > window_width ) {
+ // Place tooltip_notification on the other side, taking into account the arrow's size
+ // The left margin of the tooltip_notification and half the
+ // arrow's size is 16px
+ tooltip_notification_left = tooltip_target_left - tooltip_notification_width - 16;
+ // Why does 4px work perfectly here?
+ tooltip_notification.children("div[class='ttn_arrow']").css("left", (tooltip_notification_width - 4) + "px");
+ tooltip_notification.children("div[class='ttn_arrow']").css("border-color", "transparent transparent transparent #FFFFCC");
+ tooltip_notification.children("div[class='ttn_arrow']").css("border-color", "rgba(255,255,255,0) rgba(255,255,255,0) rgba(255,255,255,0) #FFFFCC");
+ // 2px is 4px - 2px here, since the arrow's border has a 2px offset from the arrow
+ tooltip_notification.children("div[class='ttn_arrow_border']").css("left", "").css("left", (tooltip_notification_width - 2) + "px");
+ tooltip_notification.children("div[class='ttn_arrow_border']").css("border-color", "transparent transparent transparent #FFCC00");
+ tooltip_notification.children("div[class='ttn_arrow_border']").css("border-color", "rgba(255,255,255,0) rgba(255,255,255,0) rgba(255,255,255,0) #FFCC00");
+ tooltip_notification.css("-moz-box-shadow", "-1px 1px 3px gray");
+ tooltip_notification.css("-webkit-box-shadow", "-1px 1px 3px gray");
+ tooltip_notification.css("-o-box-shadow", "-1px 1px 3px gray");
+ tooltip_notification.css("box-shadow", "-1px 1px 3px gray");
+ }
+ else {
+ // The original left position of the tooltip_notification's arrow is -14px
+ tooltip_notification.children("div[class='ttn_arrow']").css("left", "-14px");
+ tooltip_notification.children("div[class='ttn_arrow']").css("border-color", "transparent #FFFFCC transparent transparent");
+ tooltip_notification.children("div[class='ttn_arrow']").css("border-color", "rgba(255,255,255,0) #FFFFCC rgba(255,255,255,0) rgba(255,255,255,0)");
+ // The original left position of the tooltip_notification's arrow border is -16px
+ tooltip_notification.children("div[class='ttn_arrow_border']").css("left", "").css("left", "-16px");
+ tooltip_notification.children("div[class='ttn_arrow_border']").css("border-color", "transparent #FFCC00 transparent transparent");
+ tooltip_notification.children("div[class='ttn_arrow_border']").css("border-color", "rgba(255,255,255,0) #FFCC00 rgba(255,255,255,0) rgba(255,255,255,0)");
+ tooltip_notification.css("-moz-box-shadow", "1px 1px 3px gray");
+ tooltip_notification.css("-webkit-box-shadow", "1px 1px 3px gray");
+ tooltip_notification.css("-o-box-shadow", "1px 1px 3px gray");
+ tooltip_notification.css("box-shadow", "1px 1px 3px gray");
+ }
+
+ // Set the final attributes for tooltip_notification
+ tooltip_notification.css('top', tooltip_notification_top + 'px');
+ tooltip_notification.css('left', tooltip_notification_left + 'px');
+
+ // If the tooltip_notification was previously hidden, show it.
+ if ( !tooltip_notification.is(":visible") ) {
+ tooltip_notification.show();
+ }
+
+ }
+
+ else {
+
+ // If the tooltip_notification was previously visible, hide it.
+ if ( tooltip_notification.is(":visible") ) {
+ tooltip_notification.hide();
+ }
+
+ }
+
+}
+
diff --git a/modules/webnews/lib/webnews.py b/modules/webnews/lib/webnews.py
new file mode 100644
index 0000000000..a1d15dfae8
--- /dev/null
+++ b/modules/webnews/lib/webnews.py
@@ -0,0 +1,291 @@
+# -*- coding: utf-8 -*-
+##
+## This file is part of Invenio.
+## Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 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.
+
+""" WebNews module """
+
+__revision__ = "$Id$"
+
+# GENERAL IMPORTS
+from cgi import escape
+import sys
+CFG_JSON_AVAILABLE = True
+if sys.hexversion < 0x2060000:
+ try:
+ import simplejson as json
+ except:
+ CFG_JSON_AVAILABLE = False
+else:
+ import json
+
+# GENERAL IMPORTS
+from urlparse import urlsplit
+import time
+
+# INVENIO IMPORTS
+from invenio.config import CFG_SITE_LANG
+from invenio.webinterface_handler_wsgi_utils import Cookie, \
+ get_cookie
+ # INFO: Old API, ignore
+ #add_cookies, \
+from invenio.messages import gettext_set_language
+from invenio.urlutils import get_referer
+
+# MODULE IMPORTS
+from invenio.webnews_dblayer import get_latest_story_id, \
+ get_story_tooltips
+from invenio.webnews_config import CFG_WEBNEWS_TOOLTIPS_DISPLAY, \
+ CFG_WEBNEWS_TOOLTIPS_COOKIE_LONGEVITY, \
+ CFG_WEBNEWS_TOOLTIPS_COOKIE_NAME
+
+def _create_tooltip_cookie(name = CFG_WEBNEWS_TOOLTIPS_COOKIE_NAME,
+ value = "",
+ path = "/",
+ longevity = CFG_WEBNEWS_TOOLTIPS_COOKIE_LONGEVITY):
+ """
+ Private shortcut function that returns an instance of a Cookie for the
+ tooltips.
+ """
+
+ # The local has to be English for this to work!
+ longevity_time = time.time() + ( longevity * 24 * 60 * 60 )
+ longevity_expression = time.strftime("%a, %d-%b-%Y %T GMT", time.gmtime(longevity_time))
+
+ cookie = Cookie(name,
+ value,
+ path = path,
+ expires = longevity_expression)
+
+ return cookie
+
+def _paths_match(path1, path2):
+ """
+ Internal path matcher.
+ "*" acts as a wildcard for individual path parts.
+ """
+
+ # Start off by assuming that the paths don't match
+ paths_match_p = False
+
+ # Get the individual path parts.
+ path1_parts = path1.strip("/").split("/")
+ path2_parts = path2.strip("/").split("/")
+
+ # If the 2 paths have different number of parts don't even bother checking
+ if len(path1_parts) == len(path2_parts):
+ # Check if the individual path parts match
+ for (part1, part2) in zip(path1_parts, path2_parts):
+ paths_match_p = ( part1 == part2 ) or ( "*" in (part1, part2) )
+ if not paths_match_p:
+ break
+
+ return paths_match_p
+
+def _does_referer_match_target_page(referer,
+ target_page):
+ """
+ Compares the referer and the target page in a smart way and
+ returns True if they match, otherwise False.
+ """
+
+ try:
+ return ( target_page == "*" ) or _paths_match(urlsplit(target_page)[2], urlsplit(referer)[2])
+ except:
+ return False
+
+def perform_request_tooltips(req = None,
+ uid = 0,
+ story_id = 0,
+ tooltip_id = 0,
+ ln = CFG_SITE_LANG):
+ """
+ Calculates and returns the tooltips information in JSON.
+ """
+
+ tooltips_dict = {}
+
+ #tooltips_json = json.dumps(tooltips_dict)
+ tooltips_json = '{}'
+
+ # Did we import json?
+ # Should we display tooltips at all?
+ # Does the request exist?
+ if not CFG_JSON_AVAILABLE or not CFG_WEBNEWS_TOOLTIPS_DISPLAY or req is None:
+ return tooltips_json
+
+ if story_id == 0:
+ # Is there a latest story to display?
+ story_id = get_latest_story_id()
+
+ if story_id is None:
+ return tooltips_json
+ else:
+ # Are there any tooltips associated to this story?
+ # TODO: Filter the unwanted tooltips in the DB query.
+ # We can already filter by REFERER and by the tooltips IDs in the cookie
+ # In that case we don't have to iterate through the tooltips later and
+ # figure out which ones to keep.
+ tooltips = get_story_tooltips(story_id)
+ if tooltips is None:
+ return tooltips_json
+
+ # In a more advance scenario we would save the information on whether the
+ # the user has seen the tooltips:
+ # * in a session param for the users that have logged in
+ # * in a cookie for guests
+ # We could then use a combination of these two to decide whether to display
+ # the tooltips or not.
+ #
+ # In that case, the following tools could be used:
+ #from invenio.webuser import isGuestUser, \
+ # session_param_get, \
+ # session_param_set
+ #is_user_guest = isGuestUser(uid)
+ #if not is_user_guest:
+ # try:
+ # tooltip_information = session_param_get(req, CFG_WEBNEWS_TOOLTIPS_SESSION_PARAM_NAME)
+ # except KeyError:
+ # session_param_set(req, CFG_WEBNEWS_TOOLTIPS_SESSION_PARAM_NAME, "")
+
+ cookie_name = "%s_%s" % (CFG_WEBNEWS_TOOLTIPS_COOKIE_NAME, str(story_id))
+
+ try:
+ # Get the cookie
+ cookie = get_cookie(req, cookie_name)
+ # Get the tooltip IDs that have already been displayed
+ tooltips_in_cookie = filter(None, str(cookie.value).split(","))
+ except:
+ # TODO: Maybe set a cookie with an emptry string as value?
+ tooltips_in_cookie = []
+
+ # Prepare the user's prefered language and labels.
+ _ = gettext_set_language(ln)
+ readmore_label = _("Learn more")
+ dismiss_label = _("I got it!")
+
+ # Get the referer, in order to check if we should display
+ # the tooltip in the given page.
+ referer = get_referer(req)
+
+ tooltips_list = []
+
+ for tooltip in tooltips:
+ tooltip_notification_id = 'ttn_%s_%s' % (str(story_id), str(tooltip[0]))
+ # INFO: the tooltip body is not escaped!
+ # it's up to the admin to insert proper body text.
+ #tooltip_body = escape(tooltip[1], True)
+ tooltip_body = tooltip[1]
+ tooltip_target_element = tooltip[2]
+ tooltip_target_page = tooltip[3]
+
+ # Only display the tooltips that match the referer and that the user
+ # has not already seen.
+ if _does_referer_match_target_page(referer, tooltip_target_page) and \
+ ( tooltip_notification_id not in tooltips_in_cookie ):
+
+ # Add this tooltip to the tooltips that we will display.
+ tooltips_list.append({
+ 'id' : tooltip_notification_id,
+ 'target' : tooltip_target_element,
+ 'body' : tooltip_body,
+ 'readmore' : readmore_label,
+ 'dismiss' : dismiss_label,
+ })
+
+ # Add this tooltip to the tooltips that the user has already seen.
+ #tooltips_in_cookie.append(tooltip_notification_id)
+
+ if tooltips_list:
+ # Hooray! There are some tooltips to display!
+ tooltips_dict['tooltips'] = tooltips_list
+ tooltips_dict['story_id'] = str(story_id)
+ tooltips_dict['ln'] = ln
+
+ # Create and set the updated cookie.
+ #cookie_value = ",".join(tooltips_in_cookie)
+ #cookie = _create_tooltip_cookie(cookie_name,
+ # cookie_value)
+ #req.set_cookie(cookie)
+ ## INFO: Old API, ignore
+ ##add_cookies(req, [cookie])
+
+ # JSON-ify and return the tooltips.
+ tooltips_json = json.dumps(tooltips_dict)
+ return tooltips_json
+
+def perform_request_dismiss(req = None,
+ uid = 0,
+ story_id = 0,
+ tooltip_notification_id = None):
+ """
+ Dismisses the given tooltip for the current user.
+ """
+
+ try:
+
+ if not CFG_JSON_AVAILABLE or not CFG_WEBNEWS_TOOLTIPS_DISPLAY or req is None:
+ raise Exception("Tooltips are not currently available.")
+
+ # Retrieve the story_id
+ if story_id == 0:
+ if tooltip_notification_id is None:
+ raise Exception("No tooltip_notification_id has been given.")
+ else:
+ story_id = tooltip_notification_id.split("_")[1]
+
+ # Generate the cookie name out of the story_id
+ cookie_name = "%s_%s" % (CFG_WEBNEWS_TOOLTIPS_COOKIE_NAME, str(story_id))
+
+ # Get the existing tooltip_notification_ids from the cookie
+ try:
+ # Get the cookie
+ cookie = get_cookie(req, cookie_name)
+ # Get the tooltip IDs that have already been displayed
+ tooltips_in_cookie = filter(None, str(cookie.value).split(","))
+ except:
+ # TODO: Maybe set a cookie with an emptry string as value?
+ tooltips_in_cookie = []
+
+ # Append the tooltip_notification_id to the existing tooltip_notification_ids
+ # (only if it's not there already ; but normally it shouldn't be)
+ if tooltip_notification_id not in tooltips_in_cookie:
+ tooltips_in_cookie.append(tooltip_notification_id)
+
+ # Create and set the cookie with the updated cookie value
+ cookie_value = ",".join(tooltips_in_cookie)
+ cookie = _create_tooltip_cookie(cookie_name, cookie_value)
+ req.set_cookie(cookie)
+ # INFO: Old API, ignore
+ #add_cookies(req, [cookie])
+
+ except:
+ # Something went wrong..
+ # TODO: what went wrong?
+ dismissed_p_dict = { "success" : 0 }
+ dismissed_p_json = json.dumps(dismissed_p_dict)
+ return dismissed_p_json
+ else:
+ # Everything went great!
+ dismissed_p_dict = { "success" : 1 }
+ dismissed_p_json = json.dumps(dismissed_p_dict)
+ return dismissed_p_json
+ # enable for python >= 2.5
+ #finally:
+ # # JSON-ify and return the result
+ # dismissed_p_json = json.dumps(dismissed_p_dict)
+ # return dismissed_p_json
diff --git a/modules/webnews/lib/webnews_config.py b/modules/webnews/lib/webnews_config.py
new file mode 100644
index 0000000000..c3154176f0
--- /dev/null
+++ b/modules/webnews/lib/webnews_config.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+##
+## This file is part of Invenio.
+## Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 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.
+
+""" WebNews module configuration """
+
+__revision__ = "$Id$"
+
+# Should we generally display tooltips or not?
+CFG_WEBNEWS_TOOLTIPS_DISPLAY = True
+
+# The tooltips session param name
+#CFG_WEBNEWS_TOOLTIPS_SESSION_PARAM_NAME = "has_user_seen_tooltips"
+
+# Tooltips cookie settings
+# The cookie name
+CFG_WEBNEWS_TOOLTIPS_COOKIE_NAME = "INVENIOTOOLTIPS"
+# the cookie longevity in days
+CFG_WEBNEWS_TOOLTIPS_COOKIE_LONGEVITY = 14
diff --git a/modules/webnews/lib/webnews_dblayer.py b/modules/webnews/lib/webnews_dblayer.py
new file mode 100644
index 0000000000..c013377b95
--- /dev/null
+++ b/modules/webnews/lib/webnews_dblayer.py
@@ -0,0 +1,99 @@
+# -*- coding: utf-8 -*-
+##
+## This file is part of Invenio.
+## Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 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.
+
+""" Database related functions for the WebNews module """
+
+__revision__ = "$Id$"
+
+# INVENIO IMPORTS
+from invenio.dbquery import run_sql
+
+# MODULE IMPORTS
+from invenio.webnews_utils import convert_xpath_expression_to_jquery_selector
+from invenio.webnews_config import CFG_WEBNEWS_TOOLTIPS_COOKIE_LONGEVITY
+
+def get_latest_story_id():
+ """
+ Returns the id of the latest news story available.
+ """
+
+ query = """ SELECT id
+ FROM nwsSTORY
+ WHERE created >= DATE_SUB(CURDATE(),INTERVAL %s DAY)
+ ORDER BY created DESC
+ LIMIT 1"""
+
+ params = (CFG_WEBNEWS_TOOLTIPS_COOKIE_LONGEVITY,)
+
+ res = run_sql(query, params)
+
+ if res:
+ return res[0][0]
+
+ return None
+
+def get_story_tooltips(story_id):
+ """
+ Returns all the available tooltips for the given story ID.
+ """
+
+ query = """ SELECT id,
+ body,
+ target_element,
+ target_page
+ FROM nwsTOOLTIP
+ WHERE id_story=%s"""
+
+ params = (story_id,)
+
+ res = run_sql(query, params)
+
+ if res:
+ return res
+ return None
+
+def update_tooltip(story_id,
+ tooltip_id,
+ tooltip_body,
+ tooltip_target_element,
+ tooltip_target_page,
+ is_tooltip_target_xpath = False):
+ """
+ Updates the tooltip information.
+ XPath expressions are automatically translated to the equivalent jQuery
+ selector if so chosen by the user.
+ """
+
+ query = """ UPDATE nwsTOOLTIP
+ SET body=%s,
+ target_element=%s,
+ target_page=%s
+ WHERE id=%s
+ AND id_story=%s"""
+
+ tooltip_target_element = is_tooltip_target_xpath and \
+ convert_xpath_expression_to_jquery_selector(tooltip_target_element) or \
+ tooltip_target_element
+
+ params = (tooltip_body, tooltip_target_element, tooltip_target_page, tooltip_id, story_id)
+
+ res = run_sql(query, params)
+
+ return res
+
diff --git a/modules/webnews/lib/webnews_utils.py b/modules/webnews/lib/webnews_utils.py
new file mode 100644
index 0000000000..36c0bea811
--- /dev/null
+++ b/modules/webnews/lib/webnews_utils.py
@@ -0,0 +1,62 @@
+# -*- coding: utf-8 -*-
+##
+## This file is part of Invenio.
+## Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 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.
+
+""" Utlis for the WebNews module """
+
+__revision__ = "$Id$"
+
+# GENERAL IMPORTS
+import re
+
+# CONSTANT VARIABLES
+# Regex for the nth element
+PAT_NTH = r'(\w+)\[(\d+)\]'
+def REP_NTH(matchobj):
+ return "%s:eq(%s)" % (str(matchobj.group(1)), str(int(matchobj.group(2))-1))
+FLG_NTH = 0
+# Regex for the id attribute
+PAT_IDA = r'\*\[@id=[\'"]([\w\-]+)[\'"]\]'
+REP_IDA = r'#\1'
+FLG_IDA = 0
+
+def convert_xpath_expression_to_jquery_selector(xpath_expression):
+ """
+ Given an XPath expression this function
+ returns the equivalent jQuery selector.
+ """
+
+ tmp_result = xpath_expression.strip('/')
+ tmp_result = tmp_result.split('/')
+ tmp_result = [_x2j(e) for e in zip(tmp_result, range(len(tmp_result)))]
+ jquery_selector = '.'.join(tmp_result)
+
+ return jquery_selector
+
+def _x2j((s, i)):
+ """
+ Private helper function that converts each element of an XPath expression
+ to the equivalent jQuery selector using regular expressions.
+ """
+
+ s = re.sub(PAT_IDA, REP_IDA, s, FLG_IDA)
+ s = re.sub(PAT_NTH, REP_NTH, s, FLG_NTH)
+ s = '%s("%s")' % (i and 'children' or '$', s)
+
+ return s
+
diff --git a/modules/webnews/lib/webnews_webinterface.py b/modules/webnews/lib/webnews_webinterface.py
new file mode 100644
index 0000000000..2af61fedc8
--- /dev/null
+++ b/modules/webnews/lib/webnews_webinterface.py
@@ -0,0 +1,81 @@
+## This file is part of Invenio.
+## Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 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.
+
+"""WebNews Web Interface."""
+
+__revision__ = "$Id$"
+
+__lastupdated__ = """$Date$"""
+
+# INVENIO IMPORTS
+from invenio.webinterface_handler import wash_urlargd, WebInterfaceDirectory
+from invenio.config import CFG_ACCESS_CONTROL_LEVEL_SITE, \
+ CFG_SITE_LANG
+from invenio.webuser import getUid, page_not_authorized
+
+# MODULE IMPORTS
+from invenio.webnews import perform_request_tooltips, \
+ perform_request_dismiss
+
+class WebInterfaceWebNewsPages(WebInterfaceDirectory):
+ """
+ Defines the set of /news pages.
+ """
+
+ _exports = ["tooltips", "dismiss"]
+
+ def tooltips(self, req, form):
+ """
+ Returns the news tooltips information in JSON.
+ """
+
+ argd = wash_urlargd(form, {'story_id' : (int, 0),
+ 'tooltip_id' : (int, 0),
+ 'ln' : (str, CFG_SITE_LANG)})
+
+ uid = getUid(req)
+ if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1:
+ return page_not_authorized(req, "../news/tooltip",
+ navmenuid = 'news')
+
+ tooltips_json = perform_request_tooltips(req = req,
+ uid=uid,
+ story_id=argd['story_id'],
+ tooltip_id=argd['tooltip_id'],
+ ln=argd['ln'])
+
+ return tooltips_json
+
+ def dismiss(self, req, form):
+ """
+ Dismiss the given tooltip for the current user.
+ """
+
+ argd = wash_urlargd(form, {'story_id' : (int, 0),
+ 'tooltip_notification_id' : (str, None)})
+
+ uid = getUid(req)
+ if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1:
+ return page_not_authorized(req, "../news/dismiss",
+ navmenuid = 'news')
+
+ dismissed_p_json = perform_request_dismiss(req = req,
+ uid=uid,
+ story_id=argd['story_id'],
+ tooltip_notification_id=argd['tooltip_notification_id'])
+
+ return dismissed_p_json
diff --git a/modules/webnews/web/Makefile.am b/modules/webnews/web/Makefile.am
new file mode 100644
index 0000000000..a6a1d24e56
--- /dev/null
+++ b/modules/webnews/web/Makefile.am
@@ -0,0 +1,18 @@
+## This file is part of Invenio.
+## Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 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.
+
+CLEANFILES = *~ *.tmp
diff --git a/modules/webstyle/lib/webinterface_layout.py b/modules/webstyle/lib/webinterface_layout.py
index 494dbed8d6..7534523114 100644
--- a/modules/webstyle/lib/webinterface_layout.py
+++ b/modules/webstyle/lib/webinterface_layout.py
@@ -301,6 +301,12 @@ def _lookup(self, component, path):
register_exception(alert_admin=True, subject='EMERGENCY')
WebInterfaceAuthorlistPages = WebInterfaceDumbPages
+try:
+ from invenio.webnews_webinterface import WebInterfaceWebNewsPages
+except:
+ register_exception(alert_admin=True, subject='EMERGENCY')
+ WebInterfaceWebNewsPages = WebInterfaceDumbPages
+
if CFG_OPENAIRE_SITE:
try:
from invenio.openaire_deposit_webinterface import \
@@ -369,6 +375,7 @@ class WebInterfaceInvenio(WebInterfaceSearchInterfacePages):
'goto',
'info',
'authorlist',
+ 'news',
] + test_exports + openaire_exports
def __init__(self):
@@ -410,6 +417,7 @@ def __init__(self):
yourcomments = WebInterfaceDisabledPages()
goto = WebInterfaceDisabledPages()
authorlist = WebInterfaceDisabledPages()
+ news = WebInterfaceDisabledPages()
else:
submit = WebInterfaceSubmitPages()
youraccount = WebInterfaceYourAccountPages()
@@ -442,7 +450,7 @@ def __init__(self):
yourcomments = WebInterfaceYourCommentsPages()
goto = WebInterfaceGotoPages()
authorlist = WebInterfaceAuthorlistPages()
-
+ news = WebInterfaceWebNewsPages()
# This creates the 'handler' function, which will be invoked directly
# by mod_python.
diff --git a/modules/webstyle/lib/webstyle_templates.py b/modules/webstyle/lib/webstyle_templates.py
index 316620ebaa..435de02d68 100644
--- a/modules/webstyle/lib/webstyle_templates.py
+++ b/modules/webstyle/lib/webstyle_templates.py
@@ -42,6 +42,8 @@
CFG_INSPIRE_SITE, \
CFG_WEBLINKBACK_TRACKBACK_ENABLED
+from invenio.webnews_config import CFG_WEBNEWS_TOOLTIPS_DISPLAY
+
from invenio.messages import gettext_set_language, language_list_long, is_language_rtl
from invenio.urlutils import make_canonical_urlargd, create_html_link, \
get_canonical_and_alternates_urls
@@ -389,6 +391,10 @@ def tmpl_pageheader(self, req, ln=CFG_SITE_LANG, headertitle="",
%(hepDataAdditions)s
+
+
+
+
%(metaheaderadd)s
@@ -546,6 +552,25 @@ def tmpl_pagefooter(self, req=None, ln=CFG_SITE_LANG, lastupdated=None,
else:
msg_lastupdated = ""
+ if CFG_WEBNEWS_TOOLTIPS_DISPLAY:
+ tooltips_script = """
+
+"""
+ else:
+ tooltips_script = ""
+
out = """
+%(tooltips_script)s