From 0152bea512d868cbb0d9adf33cdbf98bc2030a0f Mon Sep 17 00:00:00 2001 From: Barad Mahendra Date: Thu, 10 Apr 2014 19:46:22 +0200 Subject: [PATCH] [MERGE] [ADD] website_twitter: add twitter scroller snippet bzr revid: odo@openerp.com-20140410174622-j2waid38nk3fqitt --- addons/website_twitter/__init__.py | 2 + addons/website_twitter/__openerp__.py | 25 +++ .../website_twitter/controllers/__init__.py | 1 + addons/website_twitter/controllers/main.py | 32 ++++ addons/website_twitter/data/twitter_data.xml | 16 ++ addons/website_twitter/models/__init__.py | 3 + addons/website_twitter/models/twitter.py | 115 ++++++++++++++ .../website_twitter/models/twitter_config.py | 42 +++++ .../security/ir.model.access.csv | 2 + .../website_twitter/static/src/css/Makefile | 3 + .../static/src/css/website.twitter.css | 110 +++++++++++++ .../static/src/css/website.twitter.sass | 94 ++++++++++++ .../static/src/img/api_key.png | Bin 0 -> 39304 bytes .../static/src/img/loadtweet.gif | Bin 0 -> 16060 bytes .../static/src/img/twitter_scroll.png | Bin 0 -> 2388 bytes .../src/js/website.twitter.animation.js | 144 ++++++++++++++++++ .../static/src/js/website.twitter.editor.js | 51 +++++++ .../static/src/xml/website.twitter.xml | 45 ++++++ .../website_twitter/views/twitter_snippet.xml | 33 ++++ addons/website_twitter/views/twitter_view.xml | 56 +++++++ 20 files changed, 774 insertions(+) create mode 100644 addons/website_twitter/__init__.py create mode 100644 addons/website_twitter/__openerp__.py create mode 100644 addons/website_twitter/controllers/__init__.py create mode 100644 addons/website_twitter/controllers/main.py create mode 100644 addons/website_twitter/data/twitter_data.xml create mode 100644 addons/website_twitter/models/__init__.py create mode 100644 addons/website_twitter/models/twitter.py create mode 100644 addons/website_twitter/models/twitter_config.py create mode 100644 addons/website_twitter/security/ir.model.access.csv create mode 100644 addons/website_twitter/static/src/css/Makefile create mode 100644 addons/website_twitter/static/src/css/website.twitter.css create mode 100644 addons/website_twitter/static/src/css/website.twitter.sass create mode 100644 addons/website_twitter/static/src/img/api_key.png create mode 100644 addons/website_twitter/static/src/img/loadtweet.gif create mode 100644 addons/website_twitter/static/src/img/twitter_scroll.png create mode 100644 addons/website_twitter/static/src/js/website.twitter.animation.js create mode 100644 addons/website_twitter/static/src/js/website.twitter.editor.js create mode 100644 addons/website_twitter/static/src/xml/website.twitter.xml create mode 100644 addons/website_twitter/views/twitter_snippet.xml create mode 100644 addons/website_twitter/views/twitter_view.xml diff --git a/addons/website_twitter/__init__.py b/addons/website_twitter/__init__.py new file mode 100644 index 00000000000..396c76fe87a --- /dev/null +++ b/addons/website_twitter/__init__.py @@ -0,0 +1,2 @@ +import models +import controllers diff --git a/addons/website_twitter/__openerp__.py b/addons/website_twitter/__openerp__.py new file mode 100644 index 00000000000..96e17ff9356 --- /dev/null +++ b/addons/website_twitter/__openerp__.py @@ -0,0 +1,25 @@ +{ + 'name': 'Twitter Roller', + 'category': 'Website', + 'summary': 'Add twitter scroller snippet in website builder', + 'version': '1.0', + 'description': """ +Display best tweets +======================== + + """, + 'author': 'OpenERP SA', + 'depends': ['website'], + 'data': [ + 'security/ir.model.access.csv', + 'data/twitter_data.xml', + 'views/twitter_view.xml', + 'views/twitter_snippet.xml' + ], + 'demo': [], + 'qweb': [], + 'js': [], + 'css': [], + 'installable': True, + 'application': True, +} diff --git a/addons/website_twitter/controllers/__init__.py b/addons/website_twitter/controllers/__init__.py new file mode 100644 index 00000000000..8ee9bae18d9 --- /dev/null +++ b/addons/website_twitter/controllers/__init__.py @@ -0,0 +1 @@ +import main diff --git a/addons/website_twitter/controllers/main.py b/addons/website_twitter/controllers/main.py new file mode 100644 index 00000000000..afd636a26c4 --- /dev/null +++ b/addons/website_twitter/controllers/main.py @@ -0,0 +1,32 @@ +from openerp.addons.web import http +from openerp.addons.web.http import request +from openerp.tools.translate import _ + +import json + +class Twitter(http.Controller): + @http.route(['/twitter_reload'], type='json', auth="user", website=True) + def twitter_reload(self): + return request.website.fetch_favorite_tweets() + + @http.route(['/get_favorites'], type='json', auth="public", website=True) + def get_tweets(self, limit=20): + key = request.website.twitter_api_key + secret = request.website.twitter_api_secret + screen_name = request.website.twitter_screen_name + if not key or not secret: + return {"error": _("Please set the Twitter API Key and Secret in the Website Settings.")} + if not screen_name: + return {"error": _("Please set a Twitter screen name to load favorites from, " + "in the Website Settings (it does not have to be yours)")} + twitter_tweets = request.registry['website.twitter.tweet'] + tweets = twitter_tweets.search_read( + request.cr, request.uid, + [('website_id','=', request.website.id), + ('screen_name','=', screen_name)], + ['tweet'], limit=int(limit), order="tweet_id desc", context=request.context) + if len(tweets) < 12: + return {"error": _("Twitter user @%(username)s has less than 12 favorite tweets. " + "Please add more or choose a different screen name.") % \ + {'username': screen_name}} + return [json.loads(tweet['tweet']) for tweet in tweets] diff --git a/addons/website_twitter/data/twitter_data.xml b/addons/website_twitter/data/twitter_data.xml new file mode 100644 index 00000000000..b7ca4281504 --- /dev/null +++ b/addons/website_twitter/data/twitter_data.xml @@ -0,0 +1,16 @@ + + + + + Fetch new Twitter favorites + 2 + hours + -1 + + website + _refresh_favorite_tweets + () + + + + diff --git a/addons/website_twitter/models/__init__.py b/addons/website_twitter/models/__init__.py new file mode 100644 index 00000000000..8c34d4f968e --- /dev/null +++ b/addons/website_twitter/models/__init__.py @@ -0,0 +1,3 @@ +import twitter +import twitter_config + diff --git a/addons/website_twitter/models/twitter.py b/addons/website_twitter/models/twitter.py new file mode 100644 index 00000000000..7c1c417040b --- /dev/null +++ b/addons/website_twitter/models/twitter.py @@ -0,0 +1,115 @@ +from urllib2 import urlopen, Request, HTTPError + +import base64 +import json +import logging +import werkzeug + +from openerp.osv import fields, osv + +API_ENDPOINT = 'https://api.twitter.com' +API_VERSION = '1.1' +REQUEST_TOKEN_URL = '%s/oauth2/token' % API_ENDPOINT +REQUEST_FAVORITE_LIST_URL = '%s/%s/favorites/list.json' % (API_ENDPOINT, API_VERSION) +URLOPEN_TIMEOUT = 10 + +_logger = logging.getLogger(__name__) + +class TwitterClient(osv.osv): + _inherit = "website" + + _columns = { + 'twitter_api_key': fields.char('Twitter API key', help="Twitter API Key"), + 'twitter_api_secret': fields.char('Twitter API secret', help="Twitter API Secret"), + 'twitter_screen_name': fields.char('Get favorites from this screen name'), + } + + def _request(self, website, url, params=None): + """Send an authenticated request to the Twitter API.""" + access_token = self._get_access_token(website) + if params: + params = werkzeug.url_encode(params) + url = url + '?' + params + try: + request = Request(url) + request.add_header('Authorization', 'Bearer %s' % access_token) + return json.load(urlopen(request, timeout=URLOPEN_TIMEOUT)) + except HTTPError, e: + _logger.debug("Twitter API request failed with code: %r, msg: %r, content: %r", + e.code, e.msg, e.fp.read()) + raise + + def _refresh_favorite_tweets(self, cr, uid, context=None): + ''' called by cron job ''' + website = self.pool['website'] + ids = self.pool['website'].search(cr, uid, [('twitter_api_key', '!=', False), + ('twitter_api_secret', '!=', False), + ('twitter_screen_name', '!=', False)], + context=context) + _logger.debug("Refreshing tweets for website IDs: %r", ids) + website.fetch_favorite_tweets(cr, uid, ids, context=context) + + def fetch_favorite_tweets(self, cr, uid, ids, context=None): + website_tweets = self.pool['website.twitter.tweet'] + tweet_ids = [] + for website in self.browse(cr, uid, ids, context=context): + if not all((website.twitter_api_key, website.twitter_api_secret, + website.twitter_screen_name)): + _logger.debug("Skip fetching favorite tweets for unconfigured website %s", + website) + continue + params = {'screen_name': website.twitter_screen_name} + last_tweet = website_tweets.search_read( + cr, uid, [('website_id', '=', website.id), + ('screen_name', '=', website.twitter_screen_name)], + ['tweet_id'], + limit=1, order='tweet_id desc', context=context) + if last_tweet: + params['since_id'] = int(last_tweet[0]['tweet_id']) + _logger.debug("Fetching favorite tweets using params %r", params) + response = self._request(website, REQUEST_FAVORITE_LIST_URL, params=params) + for tweet_dict in response: + tweet_id = tweet_dict['id'] # unsigned 64-bit snowflake ID + tweet_ids = website_tweets.search(cr, uid, [('tweet_id', '=', tweet_id)]) + if not tweet_ids: + new_tweet = website_tweets.create( + cr, uid, + { + 'website_id': website.id, + 'tweet': json.dumps(tweet_dict), + 'tweet_id': tweet_id, # stored in NUMERIC PG field + 'screen_name': website.twitter_screen_name, + }, + context=context) + _logger.debug("Found new favorite: %r, %r", tweet_id, tweet_dict) + tweet_ids.append(new_tweet) + return tweet_ids + + def _get_access_token(self, website): + """Obtain a bearer token.""" + bearer_token_cred = '%s:%s' % (website.twitter_api_key, website.twitter_api_secret) + encoded_cred = base64.b64encode(bearer_token_cred) + request = Request(REQUEST_TOKEN_URL) + request.add_header('Content-Type', + 'application/x-www-form-urlencoded;charset=UTF-8') + request.add_header('Authorization', + 'Basic %s' % encoded_cred) + request.add_data('grant_type=client_credentials') + data = json.load(urlopen(request, timeout=URLOPEN_TIMEOUT)) + access_token = data['access_token'] + return access_token + +class WebsiteTwitterTweet(osv.osv): + _name = "website.twitter.tweet" + _description = "Twitter Tweets" + _columns = { + 'website_id': fields.many2one('website', string="Website"), + 'screen_name': fields.char("Screen Name"), + 'tweet': fields.text('Tweets'), + + # Twitter IDs are 64-bit unsigned ints, so we need to store them in + # unlimited precision NUMERIC columns, which can be done with a + # float field. Used digits=(0,0) to indicate unlimited. + # Using VARCHAR would work too but would have sorting problems. + 'tweet_id': fields.float("Tweet ID", digits=(0,0)), # Twitter + } diff --git a/addons/website_twitter/models/twitter_config.py b/addons/website_twitter/models/twitter_config.py new file mode 100644 index 00000000000..3330a5b0424 --- /dev/null +++ b/addons/website_twitter/models/twitter_config.py @@ -0,0 +1,42 @@ +import logging + +from openerp.osv import fields, osv +from openerp.tools.translate import _ + +_logger = logging.getLogger(__name__) + +class twitter_config_settings(osv.osv_memory): + _inherit = 'website.config.settings' + + _columns = { + 'twitter_api_key': fields.related( + 'website_id', 'twitter_api_key', type="char", + string='Twitter API Key', + help="Twitter API key you can get it from https://apps.twitter.com/app/new"), + 'twitter_api_secret': fields.related( + 'website_id', 'twitter_api_secret', type="char", + string='Twitter API secret', + help="Twitter API secret you can get it from https://apps.twitter.com/app/new"), + 'twitter_tutorial': fields.dummy( + type="boolean", string="Show me how to obtain the Twitter API Key and Secret"), + 'twitter_screen_name': fields.related( + 'website_id', 'twitter_screen_name', + type="char", string='Get favorites from this screen name', + help="Screen Name of the Twitter Account from which you want to load favorites." + "It does not have to match the API Key/Secret."), + } + + def _check_twitter_authorization(self, cr, uid, config_id, context=None): + website_obj = self.pool['website'] + website_config = self.browse(cr, uid, config_id, context=context) + try: + website_obj.fetch_favorite_tweets(cr, uid, [website_config.website_id.id], context=context) + except Exception: + _logger.warning('Failed to verify twitter API authorization', exc_info=True) + raise osv.except_osv(_('Twitter authorization error!'), _('Please double-check your Twitter API Key and Secret')) + + def create(self, cr, uid, vals, context=None): + res_id = super(twitter_config_settings, self).create(cr, uid, vals, context=context) + if vals.get('twitter_api_key') and vals.get('twitter_api_secret'): + self._check_twitter_authorization(cr, uid, res_id, context=context) + return res_id \ No newline at end of file diff --git a/addons/website_twitter/security/ir.model.access.csv b/addons/website_twitter/security/ir.model.access.csv new file mode 100644 index 00000000000..eb88063e9c5 --- /dev/null +++ b/addons/website_twitter/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_website_twitter_tweet_public,access of twitter snippet,website_twitter.model_website_twitter_tweet,,1,0,0,0 diff --git a/addons/website_twitter/static/src/css/Makefile b/addons/website_twitter/static/src/css/Makefile new file mode 100644 index 00000000000..21d0e6cdc39 --- /dev/null +++ b/addons/website_twitter/static/src/css/Makefile @@ -0,0 +1,3 @@ +sass: + sass -t expanded --compass --unix-newlines --watch website.twitter.sass:website.twitter.css + diff --git a/addons/website_twitter/static/src/css/website.twitter.css b/addons/website_twitter/static/src/css/website.twitter.css new file mode 100644 index 00000000000..b44bf800bd7 --- /dev/null +++ b/addons/website_twitter/static/src/css/website.twitter.css @@ -0,0 +1,110 @@ +.wrap-row { + position: relative; + overflow: hidden; + height: 310px; +} +.wrap-row .twitter-row { + position: absolute; + width: 100%; + height: auto; +} +.wrap-row .twitter-row div.scrollWrapper { + position: relative; + overflow: hidden; + width: 100%; + height: 100%; +} +.wrap-row .twitter-row div.scrollableArea { + position: relative; + width: auto; + height: 100%; +} +.wrap-row .twitter-row div .tweet { + border: 1px solid #cccccc; + max-width: 500px; + width: 500px; + font-size: 0.8em; + padding-top: 12px; + padding-right: 10px; + padding-bottom: 12px; + padding-left: 10px; + float: left; + display: block; + margin: 6px; + max-height: 90px; + height: 90px; + opacity: 0.6; +} +.wrap-row .twitter-row div .tweet h4, .wrap-row .twitter-row div .tweet p { + padding: 0; + margin: 0; +} +.wrap-row .twitter-row div .tweet .left { + display: block; + float: left; + width: 80px; +} +.wrap-row .twitter-row div .tweet .left img { + width: 65px; + height: auto; + float: left; + display: block; + margin: 0px 5px 0px -5px; +} +.wrap-row .twitter-row div .tweet .right { + display: block; + float: left; + width: 470px; +} +.wrap-row .twitter-row div .tweet .right .top { + height: 20px; +} +.wrap-row .twitter-row div .tweet h4 { + font-size: 14px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: bold; + color: black; + float: left; + display: block; + position: relative; + margin-left: 70px; + margin-top: -65px; +} +.wrap-row .twitter-row div .tweet h4 span { + color: #cccccc; + font-weight: bold; + font-size: 14px; +} +.wrap-row .twitter-row div .tweet p { + line-height: 1.5em; + float: left; + position: relative; + display: block; +} +.wrap-row .twitter-row div .tweet .date { + float: right; + line-height: 0.5em; + margin-top: -60px; + margin-right: -10px; +} +.wrap-row .twitter-row div .tweet .right .bottom p { + margin-top: -65px; + margin-left: 70px; + font-size: 12px; + word-break: break-word; +} +.wrap-row .twitter-row div .tweet:hover { + -webkit-box-shadow: 0.5px 0.5px 0.5px 1px #428bca; + -moz-box-shadow: 0.5px 0.5px 0.5px 1px #428bca; + box-shadow: 0.5px 0.5px 0.5px 1px #428bca; + cursor: pointer; + opacity: 1; +} + +@media screen and (max-width: 580px) { + .wrap-row { + position: relative; + overflow: hidden; + height: 100px; + } +} diff --git a/addons/website_twitter/static/src/css/website.twitter.sass b/addons/website_twitter/static/src/css/website.twitter.sass new file mode 100644 index 00000000000..9eca59eb6ce --- /dev/null +++ b/addons/website_twitter/static/src/css/website.twitter.sass @@ -0,0 +1,94 @@ +.wrap-row + position: relative + overflow: hidden + height: 310px + .twitter-row + position: absolute + width: 100% + height: auto + div + &.scrollWrapper + position: relative + overflow: hidden + width: 100% + height: 100% + &.scrollableArea + position: relative + width: auto + height: 100% + .tweet + border: 1px solid #ccc + max-width: 500px + width: 500px + font-size: 0.8em + padding-top: 12px + padding-right: 10px + padding-bottom: 12px + padding-left: 10px + float: left + display: block + margin: 6px + max-height: 90px + height: 90px + opacity: 0.6 + h4, p + padding: 0 + margin: 0 + .left + display: block + float: left + width: 80px + img + width: 65px + height: auto + float: left + display: block + margin: 0px 5px 0px -5px + .right + display: block + float: left + width: 470px + .top + height: 20px + h4 + font-size: 14px + font-family: "Helvetica Neue",Helvetica,Arial,sans-serif + font-weight: bold + color: #000 + float: left + display: block + position: relative + margin-left: 70px + margin-top: -65px + span + color: #ccc + font-weight: bold + font-size: 14px + p + line-height: 1.5em + float: left + position: relative + display: block + &.date + float: right + line-height: 0.5em + margin-top: -60px + margin-right: -10px + .right .bottom p + margin-top: -65px + margin-left: 70px + font-size: 12px + word-break: break-word + &:hover + -webkit-box-shadow: 0.5px 0.5px 0.5px 1px #428BCA + -moz-box-shadow: 0.5px 0.5px 0.5px 1px #428BCA + box-shadow: 0.5px 0.5px 0.5px 1px #428BCA + cursor: pointer + opacity: 1 + + +@media screen and (max-width: 580px) + .wrap-row + position: relative + overflow: hidden + height: 100px diff --git a/addons/website_twitter/static/src/img/api_key.png b/addons/website_twitter/static/src/img/api_key.png new file mode 100644 index 0000000000000000000000000000000000000000..8f53f9649fa92cbe43aba89e9183a49a15e1a8e1 GIT binary patch literal 39304 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 literal 0 HcmV?d00001 diff --git a/addons/website_twitter/static/src/img/loadtweet.gif b/addons/website_twitter/static/src/img/loadtweet.gif new file mode 100644 index 0000000000000000000000000000000000000000..f8a0a6179bdb8f4da5220b76f9b62c9c86b8ab50 GIT binary patch literal 16060 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
").appendTo(timeline); + openerp.jsonRpc('/get_favorites','call', {}).then(function(data) { + self.$target.find(".twitter_timeline").empty(); + if (data.error) { + self.error(data); + } + else { + self.render(data); + self.setupMouseEvents(); + } + }); + }, + stop: function() { + $(this).find('.scrollWrapper').each(function(index, el){ + self.stop_scrolling($(el)); + }); + this.clearMouseEvents(); + }, + error: function(data){ + var $error = $(qweb.render("website.Twitter.Error", {'data': data})); + $error.appendTo(this.$target.find(".twitter_timeline")); + }, + parse_tweet: function (tweet) { + var create_link = function (url, text) { + var c = $("", { + text: text, + href: url, + target: "_blank" + }); + return c.prop("outerHTML"); + }; + return tweet.text.replace(/[A-Za-z]+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&~\?\/.=]+/g, + function (url) { return create_link(url, url) }) + .replace(/[@]+[A-Za-z0-9_]+/g, + function (screen_name) { return create_link("http://twitter.com/" + screen_name.replace("@",""), screen_name); }) + .replace(/[#]+[A-Za-z0-9_]+/g, + function (hashtag) { return create_link("http://twitter.com/search?q="+hashtag.replace("#",""), hashtag); }); + }, + parse_date: function(tweet) { + var d = new Date(tweet.created_at); + return d.toDateString(); + }, + setupMouseEvents: function() { + var self = this; + this.$scroller.mouseenter(function() { + $(this).find('.scrollWrapper').each(function(index, el){ + self.stop_scrolling($(el)); + }); + }).mouseleave(function() { + $(this).find('.scrollWrapper').each(function(index, el){ + self.start_scrolling($(el)); + }); + }); + }, + clearMouseEvents: function() { + if (this.$scroller) { + this.$scroller.off('mouseenter') + .off('mouseleave'); + } + }, + render: function(data){ + var self = this; + var timeline = this.$target.find(".twitter_timeline"); + var tweets = []; + $.each(data, function (e, tweet) { + tweet.created_at = self.parse_date(tweet); + tweet.text = self.parse_tweet(tweet); + tweets.push(qweb.render("website.Twitter.Tweet", {'tweet': tweet})); + }); + + var f = Math.floor(tweets.length / 3); + var tweet_slice = [tweets.slice(0, f).join(" "), tweets.slice(f, f * 2).join(" "), tweets.slice(f * 2, tweets.length).join(" ")]; + + this.$scroller = $(qweb.render("website.Twitter.Scroller")); + this.$scroller.appendTo(this.$target.find(".twitter_timeline")); + this.$scroller.find("div[id^='scroller']").each(function(index, element){ + var scrollWrapper = $('
'); + var scrollableArea = $('
'); + scrollWrapper.append(scrollableArea) + .data('scrollableArea', scrollableArea); + scrollableArea.append(tweet_slice[index]); + $(element).append(scrollWrapper); + scrollableArea.width(self.get_wrapper_width(scrollableArea)); + scrollWrapper.scrollLeft(index*180); + self.start_scrolling(scrollWrapper); + }); + }, + get_wrapper_width: function(wrapper){ + var total_width = 0; + wrapper.children().each(function(){ + total_width += $(this).outerWidth(true); + }); + return total_width; + }, + start_scrolling: function(wrapper){ + var self = this; + wrapper.data("getNextElementWidth", true); + wrapper.data("autoScrollingInterval", setInterval(function () { + wrapper.scrollLeft(wrapper.scrollLeft() + 1); + self.swap_right(wrapper); + }, 20)); + }, + stop_scrolling: function(wrapper){ + clearInterval(wrapper.data('autoScrollingInterval')); + }, + swap_right: function(wrapper){ + if (wrapper.data("getNextElementWidth")) { + wrapper.data("swapAt", wrapper.data("scrollableArea").children(":first").outerWidth(true)); + wrapper.data("getNextElementWidth", false); + } + if (wrapper.data("swapAt") <= wrapper.scrollLeft()){ + var swap_el = wrapper.data("scrollableArea").children(":first").detach(); + wrapper.data("scrollableArea").append(swap_el); + wrapper.scrollLeft(wrapper.scrollLeft() - swap_el.outerWidth(true)); + wrapper.data("getNextElementWidth", true); + } + }, + }); + +})(); diff --git a/addons/website_twitter/static/src/js/website.twitter.editor.js b/addons/website_twitter/static/src/js/website.twitter.editor.js new file mode 100644 index 00000000000..69a1896695a --- /dev/null +++ b/addons/website_twitter/static/src/js/website.twitter.editor.js @@ -0,0 +1,51 @@ +(function () { + 'use strict'; + var website = openerp.website, + qweb = openerp.qweb; + + website.snippet.options["twitter"] = website.snippet.options.marginAndResize.extend({ + start: function(){ + this._super(); + this.make_hover_config(); + this.$target.find('.lnk_configure').click(function(e){ + window.location = e.target.href; + }); + if (this.$target.data("snippet-view")) { + this.$target.data("snippet-view").stop(); + } + }, + twitter_reload: function(){ + openerp.jsonRpc('/twitter_reload','call', {}); + }, + make_hover_config: function(){ + var self = this; + var $configuration = $(qweb.render("website.Twitter.Reload")).hide().appendTo(document.body).click(function (e) { + e.preventDefault(); + e.stopPropagation(); + self.twitter_reload(); + }); + this.$target.on('mouseover', '', function () { + var $selected = $(this); + var position = $selected.offset(); + $configuration.show().offset({ + top: $selected.outerHeight() / 2 + + position.top + - $configuration.outerHeight() / 2, + left: $selected.outerWidth() / 2 + + position.left + - $configuration.outerWidth() / 2, + }) + }).on('mouseleave', '', function (e) { + var current = document.elementFromPoint(e.clientX, e.clientY); + if (current === $configuration[0]) { + return; + } + $configuration.hide(); + }); + }, + clean_for_save: function () { + this.$target.find(".twitter_timeline").empty(); + }, + }); + +})(); diff --git a/addons/website_twitter/static/src/xml/website.twitter.xml b/addons/website_twitter/static/src/xml/website.twitter.xml new file mode 100644 index 00000000000..25c6121e166 --- /dev/null +++ b/addons/website_twitter/static/src/xml/website.twitter.xml @@ -0,0 +1,45 @@ + + + + +
+ + +
+ +
+
+ + + + + + + diff --git a/addons/website_twitter/views/twitter_snippet.xml b/addons/website_twitter/views/twitter_snippet.xml new file mode 100644 index 00000000000..bc039d71c61 --- /dev/null +++ b/addons/website_twitter/views/twitter_snippet.xml @@ -0,0 +1,33 @@ + + + + + + + + diff --git a/addons/website_twitter/views/twitter_view.xml b/addons/website_twitter/views/twitter_view.xml new file mode 100644 index 00000000000..8600ceca039 --- /dev/null +++ b/addons/website_twitter/views/twitter_view.xml @@ -0,0 +1,56 @@ + + + + + Twitter settings + website.config.settings + + + + + + + +