@ -0,0 +1,25 @@ |
|||
==================== |
|||
User Weather Map v10 |
|||
==================== |
|||
|
|||
This module provides a weather notification for every users. |
|||
|
|||
Installation |
|||
============ |
|||
|
|||
Make sure you have ``pytemperature`` Python module installed:: |
|||
|
|||
$ pip install pytemperature |
|||
|
|||
Make an account in "openweathermap.org", generate a API Key. |
|||
|
|||
Features |
|||
======== |
|||
|
|||
* User can get the weather notification. |
|||
* User can configure there weather notification. |
|||
* User's place can set by address or coordinates. |
|||
|
|||
Credits |
|||
======= |
|||
Nikhil Krishnan @ cybrosys, nikhil@cybrosys.in |
@ -0,0 +1,24 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Nikhil krishnan(<https://www.cybrosys.com>) |
|||
# you can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# It is forbidden to publish, distribute, sublicense, or sell copies |
|||
# of the Software or modified copies of the Software. |
|||
# |
|||
# This program 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
import models |
@ -0,0 +1,48 @@ |
|||
# -*- coding: utf-8 -*- |
|||
|
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Nikhil krishnan(<https://www.cybrosys.com>) |
|||
# you can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# It is forbidden to publish, distribute, sublicense, or sell copies |
|||
# of the Software or modified copies of the Software. |
|||
# |
|||
# This program 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
{ |
|||
'name': 'User Weather Map', |
|||
'version': '10.0.1.0', |
|||
'summary': """Get User's Weather From OpenWeatherMap Automatically.""", |
|||
'description': """Get User's Weather and Temperature From OpenWeatherMap Automatically.""", |
|||
'author': 'Cybrosys Techno Solutions', |
|||
'company': 'Cybrosys Techno Solutions', |
|||
'website': 'http://www.cybrosys.com', |
|||
'category': 'Tools', |
|||
'depends': ['base'], |
|||
'external_dependencies': {'python': ['pytemperature']}, |
|||
'license': 'LGPL-3', |
|||
'data': [ |
|||
'security/ir.model.access.csv', |
|||
'views/weather_template.xml', |
|||
'views/weather_conf.xml', |
|||
], |
|||
'demo': [], |
|||
'qweb': [ |
|||
"static/src/xml/weather_topbar.xml", |
|||
], |
|||
'images': ['static/description/banner.jpg'], |
|||
'installable': True, |
|||
'auto_install': False, |
|||
} |
@ -0,0 +1,25 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Nikhil krishnan(<https://www.cybrosys.com>) |
|||
# you can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# It is forbidden to publish, distribute, sublicense, or sell copies |
|||
# of the Software or modified copies of the Software. |
|||
# |
|||
# This program 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
import weather |
@ -0,0 +1,413 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<http://www.cybrosys.com>). |
|||
# Author: Nikhil krishnan(<http://www.cybrosys.com>) |
|||
# you can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# It is forbidden to publish, distribute, sublicense, or sell copies |
|||
# of the Software or modified copies of the Software. |
|||
# |
|||
# This program 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
import pytz |
|||
from pytz import timezone |
|||
from dateutil.relativedelta import relativedelta |
|||
from datetime import datetime |
|||
|
|||
try: |
|||
import pytemperature |
|||
except ImportError: |
|||
print 'pytemperature, this python package is not available. please install by using ' \ |
|||
'==> pip install pytemperature' |
|||
pass |
|||
|
|||
try: |
|||
import simplejson as json |
|||
except ImportError: |
|||
import json # noqa |
|||
import urllib |
|||
|
|||
import odoo |
|||
from odoo import models, fields, api |
|||
from odoo import tools |
|||
from odoo.tools.translate import _ |
|||
|
|||
|
|||
class UserWeatherMap(models.Model): |
|||
_name = 'user.weather.map' |
|||
|
|||
date_weather_update = fields.Datetime(string='Last update') |
|||
name = fields.Char(string='City Name') |
|||
city = fields.Char(string='Original City') |
|||
user_id = fields.Many2one('res.users', string='User Name') |
|||
weather = fields.Char(string='Weather') |
|||
description = fields.Char(string='Description') |
|||
temp = fields.Char(string='Temperature') |
|||
pressure = fields.Char(string='Pressure') |
|||
humidity = fields.Char(string='Humidity') |
|||
min_temp = fields.Char(string='Minimum') |
|||
max_temp = fields.Char(string='Maximum') |
|||
sunset = fields.Char(string='Sunset') |
|||
sunrise = fields.Char(string='Sunrise') |
|||
|
|||
def get_weather_data(self, user_id): |
|||
user_list = self.env['res.users'].search([('id', '=', user_id)]) |
|||
if user_list.partner_id.tz: |
|||
rec = self.search([('user_id', '=', user_id)], limit=1) |
|||
tz = pytz.timezone(user_list.partner_id.tz) |
|||
now_utc = datetime.now(timezone('UTC')) |
|||
now_pacific = now_utc.astimezone(timezone(str(tz))) |
|||
current_time = now_pacific.strftime('%d %B %Y, %I:%M%p') |
|||
current_date = now_pacific.strftime('%d %B %Y') |
|||
if rec: |
|||
current_date_time = datetime.strptime(current_time, '%d %B %Y, %I:%M%p') |
|||
last_update = datetime.strptime(rec.date_weather_update, '%Y-%m-%d %H:%M:%S') |
|||
new_update_allowed_time = last_update + relativedelta(minutes=1) |
|||
if current_date_time > new_update_allowed_time: |
|||
get_weather = self.get_weather(user_id) |
|||
if get_weather: |
|||
if get_weather['issue'] == 'bad_request': |
|||
return { |
|||
'issue': 'Bad Request' |
|||
} |
|||
elif get_weather['issue'] == 'internet': |
|||
return { |
|||
'issue': 'Connection ERROR.!' |
|||
} |
|||
elif get_weather['issue'] == 'localization': |
|||
return { |
|||
'issue': 'longitude and latitude or address issue.' |
|||
} |
|||
elif get_weather['issue'] == 'config': |
|||
return { |
|||
'issue': 'Weather configuration not set yet.' |
|||
} |
|||
elif get_weather['issue'] == 'timezone': |
|||
return { |
|||
'issue': 'Timezone is not available' |
|||
} |
|||
else: |
|||
rec = self.search([('user_id', '=', user_id)], limit=1) |
|||
else: |
|||
pass |
|||
|
|||
if rec: |
|||
vals = { |
|||
'date_now': current_date, |
|||
'date_weather_update': rec.date_weather_update, |
|||
'name': rec.name, |
|||
'city': rec.city, |
|||
'user_id': rec.user_id.id, |
|||
'weather': rec.weather, |
|||
'description': rec.description, |
|||
'temp': rec.temp, |
|||
'pressure': rec.pressure, |
|||
'humidity': rec.humidity, |
|||
'min_temp': rec.min_temp, |
|||
'max_temp': rec.max_temp, |
|||
'issue': '', |
|||
} |
|||
return vals |
|||
else: |
|||
get_weather = self.get_weather(user_id) |
|||
if get_weather['issue'] == 'bad_request': |
|||
return { |
|||
'issue': 'Bad Request' |
|||
} |
|||
elif get_weather['issue'] == 'internet': |
|||
return { |
|||
'issue': 'Connection ERROR.!' |
|||
} |
|||
elif get_weather['issue'] == 'localization': |
|||
return { |
|||
'issue': 'Set correct Location' |
|||
} |
|||
elif get_weather['issue'] == 'config': |
|||
return { |
|||
'issue': 'Weather configuration not set yet.' |
|||
} |
|||
elif get_weather['issue'] == 'timezone': |
|||
return { |
|||
'issue': 'Timezone is not available' |
|||
} |
|||
else: |
|||
rec = self.search([('user_id', '=', user_id)], limit=1) |
|||
if rec: |
|||
vals = { |
|||
'date_now': current_date, |
|||
'date_weather_update': rec.date_weather_update, |
|||
'name': rec.name, |
|||
'city': rec.city, |
|||
'user_id': rec.user_id.id, |
|||
'weather': rec.weather, |
|||
'description': rec.description, |
|||
'temp': rec.temp, |
|||
'pressure': rec.pressure, |
|||
'humidity': rec.humidity, |
|||
'min_temp': rec.min_temp, |
|||
'max_temp': rec.max_temp, |
|||
'issue': '', |
|||
} |
|||
return vals |
|||
else: |
|||
return { |
|||
'issue': 'Bad request' |
|||
} |
|||
|
|||
else: |
|||
return { |
|||
'issue': 'Timezone is not available' |
|||
} |
|||
|
|||
def get_weather(self, user_id): |
|||
rec = self.env['user.weather.map.config'].search([('user_id', '=', user_id)], limit=1) |
|||
if rec: |
|||
weather_path = 'http://api.openweathermap.org/data/2.5/weather?' |
|||
if rec.u_longitude and rec.u_latitude: |
|||
params = urllib.urlencode( |
|||
{'lat': rec.u_latitude, 'lon': rec.u_longitude, 'APPID': rec.appid}) |
|||
elif rec.city: |
|||
params = urllib.urlencode( |
|||
{'q': rec.city, 'APPID': rec.appid}) |
|||
else: |
|||
return { |
|||
'issue': 'localization' |
|||
} |
|||
|
|||
url = weather_path + params |
|||
try: |
|||
f = urllib.urlopen(url) |
|||
except Exception: |
|||
f = False |
|||
if f: |
|||
ret = f.read().decode('utf-8') |
|||
result = json.loads(ret) |
|||
if result: |
|||
if "cod" in result.keys(): |
|||
if result['cod'] == 200: |
|||
city = False |
|||
city2 = False |
|||
if "name" in result.keys(): |
|||
city = result['name'] |
|||
if not city: |
|||
if rec.method == 'address': |
|||
city = rec.city |
|||
if rec.method == 'address': |
|||
city2 = rec.city |
|||
|
|||
temp = pytemperature.k2c(result['main']['temp']) |
|||
min_temp = pytemperature.k2c(result['main']['temp_min']) |
|||
max_temp = pytemperature.k2c(result['main']['temp_max']) |
|||
weather_rec = self.search([('user_id', '=', rec.user_id.id)]) |
|||
now_utc = datetime.now(timezone('UTC')) |
|||
user_list = self.env['res.users'].search([('id', '=', user_id)]) |
|||
if user_list.partner_id.tz: |
|||
tz = pytz.timezone(user_list.partner_id.tz) |
|||
now_pacific = now_utc.astimezone(timezone(str(tz))) |
|||
current_time = now_pacific.strftime('%d %B %Y, %I:%M%p') |
|||
vals = { |
|||
'date_weather_update': current_time, |
|||
'name': city, |
|||
'city': city2, |
|||
'user_id': user_id, |
|||
'weather': result['weather'][0]['main'], |
|||
'description': result['weather'][0]['description'], |
|||
'temp': temp, |
|||
'pressure': result['main']['pressure'], |
|||
'humidity': result['main']['humidity'], |
|||
'min_temp': min_temp, |
|||
'max_temp': max_temp, |
|||
} |
|||
if weather_rec: |
|||
weather_rec.write(vals) |
|||
return { |
|||
'issue': '' |
|||
} |
|||
else: |
|||
weather_rec.create(vals) |
|||
return { |
|||
'issue': '' |
|||
} |
|||
else: |
|||
return { |
|||
'issue': 'timezone' |
|||
} |
|||
else: |
|||
return { |
|||
'issue': 'localization' |
|||
} |
|||
else: |
|||
return { |
|||
'issue': 'bad_request' |
|||
} |
|||
else: |
|||
return { |
|||
'issue': 'internet' |
|||
} |
|||
else: |
|||
return { |
|||
'issue': 'config' |
|||
} |
|||
|
|||
|
|||
class UserWeatherMapConfig(models.Model): |
|||
_name = 'user.weather.map.config' |
|||
_inherit = 'res.config.settings' |
|||
_rec_name = 'user_id' |
|||
|
|||
def _default_street(self): |
|||
rec = self.search([('user_id', '=', self.env.user.id)]) |
|||
if rec: |
|||
return rec.street |
|||
|
|||
def _default_city(self): |
|||
rec = self.search([('user_id', '=', self.env.user.id)]) |
|||
if rec: |
|||
return rec.city |
|||
|
|||
def _default_state_id(self): |
|||
rec = self.search([('user_id', '=', self.env.user.id)]) |
|||
if rec: |
|||
return rec.state_id.id |
|||
|
|||
def _default_country_id(self): |
|||
rec = self.search([('user_id', '=', self.env.user.id)]) |
|||
if rec: |
|||
return rec.country_id.id |
|||
|
|||
def _default_zip(self): |
|||
rec = self.search([('user_id', '=', self.env.user.id)]) |
|||
if rec: |
|||
return rec.zip |
|||
|
|||
def _default_appid(self): |
|||
rec = self.search([('user_id', '=', self.env.user.id)]) |
|||
if rec: |
|||
return rec.appid |
|||
|
|||
def _default_method(self): |
|||
rec = self.search([('user_id', '=', self.env.user.id)]) |
|||
if rec: |
|||
return rec.method |
|||
else: |
|||
return 'address' |
|||
|
|||
def _default_longitude(self): |
|||
rec = self.search([('user_id', '=', self.env.user.id)]) |
|||
if rec: |
|||
if rec.method == 'coordinates': |
|||
return rec.u_longitude |
|||
else: |
|||
return '' |
|||
|
|||
def _default_latitude(self): |
|||
rec = self.search([('user_id', '=', self.env.user.id)]) |
|||
if rec: |
|||
if rec.method == 'coordinates': |
|||
return rec.u_latitude |
|||
else: |
|||
return '' |
|||
|
|||
user_id = fields.Many2one('res.users', string='User Name', readonly=True, default=lambda self: self.env.user.id) |
|||
u_longitude = fields.Char(string='Longitude', default=_default_longitude) |
|||
u_latitude = fields.Char(string='Latitude', default=_default_latitude) |
|||
|
|||
street = fields.Char('Street', default=_default_street) |
|||
zip = fields.Char('Zip', size=24, change_default=True, default=_default_zip) |
|||
city = fields.Char('City', default=_default_city) |
|||
state_id = fields.Many2one("res.country.state", string='State', ondelete='restrict', default=_default_state_id) |
|||
country_id = fields.Many2one('res.country', string='Country', ondelete='restrict', default=_default_country_id) |
|||
appid = fields.Char('App id', default=_default_appid, required=True, |
|||
help="Just sign up the OpenWeatherMap. Generate a Weather Key and provide here.") |
|||
method = fields.Selection([('address', 'By Address'), |
|||
('coordinates', 'By geolocation')], string='Type', default=_default_method) |
|||
|
|||
@api.multi |
|||
def onchange_state(self, state_id): |
|||
if state_id: |
|||
state = self.env['res.country.state'].browse(state_id) |
|||
return {'value': {'country_id': state.country_id.id}} |
|||
return {} |
|||
|
|||
|
|||
@api.multi |
|||
def execute_weather(self): |
|||
val = 0 |
|||
recs = self.search([('user_id', '=', self.user_id.id)]) |
|||
for rec1 in recs: |
|||
if val < rec1.id: |
|||
val = rec1.id |
|||
for rec2 in recs: |
|||
if val != rec2.id: |
|||
rec2.unlink() |
|||
if self.method == 'address': |
|||
self.geo_localize() |
|||
else: |
|||
pass |
|||
self.env['user.weather.map'].get_weather(self.user_id.id) |
|||
return { |
|||
'type': 'ir.actions.act_url', |
|||
'url': '/web', |
|||
'target': 'self', |
|||
} |
|||
|
|||
def geo_query_address(self, street=None, zip=None, city=None, state=None, country=None): |
|||
if country and ',' in country and (country.endswith(' of') or country.endswith(' of the')): |
|||
# put country qualifier in front, otherwise GMap gives wrong results, |
|||
# e.g. 'Congo, Democratic Republic of the' => 'Democratic Republic of the Congo' |
|||
country = '{1} {0}'.format(*country.split(',', 1)) |
|||
return tools.ustr(', '.join(filter(None, [street, |
|||
("%s %s" % (zip or '', city or '')).strip(), |
|||
state, |
|||
country]))) |
|||
|
|||
def geo_find(self, addr): |
|||
url = 'https://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=' |
|||
url += urllib.quote(addr.encode('utf8')) |
|||
try: |
|||
result = json.load(urllib.urlopen(url)) |
|||
except Exception, e: |
|||
raise odoo.exceptions.except_orm(_('Network error'), |
|||
_('Cannot contact geolocation servers. ' |
|||
'Please make sure that your internet connection is up and running (%s).') % e) |
|||
if result['status'] != 'OK': |
|||
return None |
|||
|
|||
try: |
|||
geo = result['results'][0]['geometry']['location'] |
|||
return float(geo['lat']), float(geo['lng']) |
|||
except (KeyError, ValueError): |
|||
return None |
|||
|
|||
@api.one |
|||
def geo_localize(self): |
|||
# Don't pass context to browse()! We need country names in english below |
|||
result = self.geo_find(self.geo_query_address(street=self.street, |
|||
zip=self.zip, |
|||
city=self.city, |
|||
state=self.state_id.name, |
|||
country=self.country_id.name)) |
|||
if result: |
|||
self.write({ |
|||
'u_latitude': result[0], |
|||
'u_longitude': result[1], |
|||
}, ) |
|||
else: |
|||
if self.method == 'address': |
|||
self.write({ |
|||
'u_latitude': '', |
|||
'u_longitude': '', |
|||
}, ) |
|||
return True |
|
After Width: | Height: | Size: 69 KiB |
After Width: | Height: | Size: 123 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 11 KiB |
@ -0,0 +1,222 @@ |
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h2 class="oe_slogan">User Weather Notification</h2> |
|||
<h3 class="oe_slogan">Real time Weather updates</h3> |
|||
<h4 class="oe_slogan"><a href="https://www.cybrosys.com">Cybrosys Technologies</a> </h4> |
|||
<div> |
|||
<h4><p>Features:</p></h4> |
|||
<ul> |
|||
<li style="list-style:none !important;"><span style="color:green;"> ☑</span> The user will get the weather notification.</li> |
|||
<li style="list-style:none !important;"> |
|||
<span style="color:green;"> ☑</span> The user can configure their weather notification. |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
<div> |
|||
<h4><p>Required:</p></h4> |
|||
<ul> |
|||
<li style="list-style:none !important;"><span style="color:red;"> ☑</span> Account in Open Weather Map and its API Key.</li> |
|||
<li style="list-style:none !important;"> |
|||
<span style="color:red;"> ☑</span> 'pytemperature' python package is needed. please install in ubuntu by using ==> pip install pytemperature. |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container oe_dark"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h3 class="oe_slogan">Overview</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span12"> |
|||
<p class="oe_mt32"> |
|||
As we know, many industries are depending on weather conditions like manufacturing, |
|||
Event Management, Construction etc. So we believe our concept of weather module can be used |
|||
in these industries to understand and plan their works according to the weather condition. |
|||
This module is a starter to think and explore the opportunity to bring the advanced features |
|||
in Odoo. |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
|
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h3 class="oe_slogan">Weather notification in Odoo</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span12"> |
|||
<div class="oe_row_img oe_centered"> |
|||
<img class="oe_picture oe_screenshot" src="weather Board.png"> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="oe_span12"> |
|||
<p class="oe_mt32"/> |
|||
<p class="oe_mt32"> |
|||
User can easily find the weather report from a single click. Summary of the weather |
|||
conditions is displayed on the weather board. The user will easily get weather updates, |
|||
state of climate and current temperature etc.. |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container oe_dark"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h2 class="oe_slogan" style="color:#875A7B;">Enjoy advanced and automated weather update</h2> |
|||
<h3 class="oe_slogan">The most advanced weather notification in a very simple user interface |
|||
</h3> |
|||
<p class="oe_mt32 oe_mb64 lead text-center"> |
|||
Avoid search for weather updates, get it in a single click. |
|||
This module integrates the weather into the Odoo system. |
|||
</p> |
|||
<div class="oe_span4"> |
|||
<div class="text-center"> |
|||
<span class="fa fa-users fa-4x"/> |
|||
<h4 class="oe_mt16 oe_mb16"> |
|||
<b>Users</b> |
|||
</h4> |
|||
</div> |
|||
<p class="text-justify"> |
|||
Nowadays everyone is searching temperature and weather conditions in their city or any other |
|||
location by using search engines, here we have a very flexible way to find out it easily through |
|||
our module without any surfing. |
|||
</p> |
|||
</div> |
|||
<div class="oe_span4"> |
|||
<div class="text-center"> |
|||
<span class="fa fa-cog fa-4x"/> |
|||
<h4 class="oe_mt16 oe_mb16"> |
|||
<b>Settings</b> |
|||
</h4> |
|||
</div> |
|||
<p class="text-justify"> |
|||
User can specify their current location or any location by providing address or coordinates. |
|||
</p> |
|||
</div> |
|||
<div class="oe_span4"> |
|||
<div class="text-center"> |
|||
<span class="fa fa-circle-o fa-4x" style="color:#875a7b;"/> |
|||
<span class="fa fa-long-arrow-left fa-3x"/> |
|||
<span class="fa fa-cloud fa-4x" style="color:#ce671c;"/> |
|||
<h4 class="oe_mt16 oe_mb16"> |
|||
<b>Open Weather Map</b> |
|||
</h4> |
|||
</div> |
|||
<p class="text-justify"> |
|||
openweathermap.org is providing weather APIs calls and response. Odoo is using this API and provides |
|||
you the best result by the help of our application. |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h3 class="oe_slogan">How to configure your weather?</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span12"> |
|||
<div class="oe_row_img oe_centered"> |
|||
<img class="oe_picture oe_screenshot" src="settings.png"> |
|||
</div> |
|||
<p class="oe_mt32"> |
|||
Click on the setting (<span class="fa fa-cog fa-1x"/>) button. |
|||
</p> |
|||
</div> |
|||
<div class="oe_span12"> |
|||
<div class="oe_row_img oe_centered"> |
|||
<img class="oe_picture oe_screenshot" src="config.png"> |
|||
</div> |
|||
</div> |
|||
<div class="oe_span12"> |
|||
<p class="oe_mt32"> |
|||
Users can give address of the place or coordinates by selecting the type, |
|||
<p> |
|||
If you are selecting the address type, please provide the address and If it is coordinate, |
|||
then give the correct longitude and latitude. |
|||
</p> |
|||
</p> |
|||
<p class="oe_mt32"> |
|||
Provide the correct API key received from the OpenWeatherMap site. |
|||
</p> |
|||
</div> |
|||
|
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container oe_dark"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h3 class="oe_slogan">How to get API KEY?</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
Click on the Sing up (<span class="fa fa-sign-in fa-1x"/>) button. |
|||
</div> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span12"> |
|||
<div class="oe_row_img oe_centered"> |
|||
<img class="oe_picture oe_screenshot" src="sign up.png"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="oe_row oe_spaced"> |
|||
It will go to the account creation page of Open Weather Map |
|||
</div> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span12"> |
|||
<div class="oe_row_img oe_centered"> |
|||
<img class="oe_picture oe_screenshot" src="sign_up_weather_map.png"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="oe_row oe_spaced"> |
|||
Fill the required fields and create an account. |
|||
</div> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span12"> |
|||
<div class="oe_row_img oe_centered"> |
|||
<img class="oe_picture oe_screenshot" src="fill.png"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="oe_row oe_spaced"> |
|||
Once we created the account, we can use the default API Key providing by Open Weather Map or |
|||
else you have an option for generating your own API Key manually. |
|||
</div> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span12"> |
|||
<div class="oe_row_img oe_centered"> |
|||
<img class="oe_picture oe_screenshot" src="api.png"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container"> |
|||
<h2 class="oe_slogan" style="margin-top:20px;" >Need Any Help?</h2> |
|||
<div class="oe_slogan" style="margin-top:10px !important;"> |
|||
<div> |
|||
<a class="btn btn-primary btn-lg mt8" |
|||
style="color: #FFFFFF !important;border-radius: 0;" href="http://www.cybrosys.com"><i |
|||
class="fa fa-envelope"></i> Email </a> <a |
|||
class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;" |
|||
href="http://www.cybrosys.com/contact/"><i |
|||
class="fa fa-phone"></i> Contact Us </a> <a |
|||
class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;" |
|||
href="http://www.cybrosys.com/odoo-customization-and-installation/"><i |
|||
class="fa fa-check-square"></i> Request Customization </a> |
|||
</div> |
|||
<br> |
|||
<img src="cybro_logo.png" style="width: 190px; margin-bottom: 20px;" class="center-block"> |
|||
<div> |
|||
<a href="https://twitter.com/cybrosys" target="_blank"><i class="fa fa-2x fa-twitter" style="color:white;background: #00a0d1;width:35px;"></i></a></td> |
|||
<a href="https://www.linkedin.com/company/cybrosys-technologies-pvt-ltd" target="_blank"><i class="fa fa-2x fa-linkedin" style="color:white;background: #31a3d6;width:35px;padding-left: 3px;"></i></a></td> |
|||
<a href="https://www.facebook.com/cybrosystechnologies" target="_blank"><i class="fa fa-2x fa-facebook" style="color:white;background: #3b5998;width:35px;padding-left: 8px;"></i></a></td> |
|||
<a href="https://plus.google.com/106641282743045431892/about" target="_blank"><i class="fa fa-2x fa-google-plus" style="color:white;background: #c53c2c;width:35px;padding-left: 3px;"></i></a></td> |
|||
<a href="https://in.pinterest.com/cybrosys" target="_blank"><i class="fa fa-2x fa-pinterest" style="color:white;background: #ac0f18;width:35px;padding-left: 3px;"></i></a></td> |
|||
</div> |
|||
</div> |
|||
</section> |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 21 KiB |
@ -0,0 +1,77 @@ |
|||
|
|||
.oe_webclient_notification_action t { |
|||
color: white; |
|||
} |
|||
.oe_webclient_notification_action p { |
|||
color: white; |
|||
margin-top: 1em; |
|||
} |
|||
.label { |
|||
display: inline-block; |
|||
color: black; |
|||
max-width: 100%; |
|||
margin-bottom: 5px; |
|||
font-weight: bold; |
|||
} |
|||
.reminder-dropdown { |
|||
.o-flex(0, 1, auto); |
|||
background: #FFFFFF; |
|||
max-height: 400px; |
|||
min-height: 50px; |
|||
overflow-y: auto; |
|||
|
|||
@media (max-width: @screen-xs-max) { |
|||
max-height: none; |
|||
} |
|||
.weather_notification { |
|||
width: 100%; |
|||
background: #eeeeee; |
|||
} |
|||
.weather_settings { |
|||
float:left; |
|||
text-align: right; |
|||
width:100%; |
|||
} |
|||
|
|||
.fa-sign-in:hover { |
|||
opacity:.5; |
|||
} |
|||
|
|||
.fa-cog{ |
|||
-webkit-transition: -webkit-transform .8s ease-in-out; |
|||
transition: transform .8s ease-in-out; |
|||
} |
|||
|
|||
.fa-cog:hover{ |
|||
-webkit-transform: rotate(360deg); |
|||
transform: rotate(360deg) ; |
|||
} |
|||
|
|||
.weather_content{ |
|||
width: 100%; |
|||
float: left; |
|||
padding-left: 5%; |
|||
padding-top: 4%; |
|||
padding-bottom: 5%; |
|||
|
|||
|
|||
} |
|||
.weather_content p{ |
|||
margin:2px 0 4px 0; |
|||
color: #808080; |
|||
font-size: 11px; |
|||
} |
|||
.weather_content h1{ |
|||
margin:0px; |
|||
font-size: 26px; |
|||
padding: 3px 0 3px 0; |
|||
} |
|||
.detail-client-address-country { |
|||
color: black; |
|||
} |
|||
.warning h4{ |
|||
color: #d21010; |
|||
font-weight: 100; |
|||
font-size: 12px; |
|||
} |
|||
|
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 998 B |
After Width: | Height: | Size: 22 KiB |
@ -0,0 +1,66 @@ |
|||
odoo.define('user_weather_map.weather_notification', function (require) { |
|||
"use strict"; |
|||
|
|||
var core = require('web.core'); |
|||
var SystrayMenu = require('web.SystrayMenu'); |
|||
var Widget = require('web.Widget'); |
|||
var Model = require('web.DataModel'); |
|||
var QWeb = core.qweb; |
|||
|
|||
var weather_menu = Widget.extend({ |
|||
template:'user_weather_map.weather_menu', |
|||
|
|||
events: { |
|||
"click .dropdown-toggle": "on_click_weather_board", |
|||
"click .fa-cog": "go_to_weather_settings", |
|||
}, |
|||
|
|||
init:function(parent, name){ |
|||
this.widget = {}; |
|||
this.reminder = null; |
|||
this._super(parent); |
|||
}, |
|||
|
|||
render_widget: function() { |
|||
var self = this; |
|||
var user = self.session.uid; |
|||
var weather = new Model('user.weather.map'); |
|||
new Model("user.weather.map").call("get_weather_data",['',user]).then(function(data){ |
|||
var weather = QWeb.render("WeatherDetails", {widget:self, |
|||
date_now: data.date_now, |
|||
date_weather_update: data.date_weather_update, |
|||
name: data.name, |
|||
city: data.city, |
|||
user_id: data.user_id, |
|||
weather: data.weather, |
|||
description: data.description, |
|||
temp: data.temp, |
|||
pressure: data.pressure, |
|||
humidity: data.humidity, |
|||
min_temp: data.min_temp, |
|||
max_temp: data.max_temp, |
|||
issue: data.issue, |
|||
}); |
|||
$('.weather_notification').html(weather); |
|||
}); |
|||
}, |
|||
|
|||
go_to_weather_settings: function (event) { |
|||
var action = { |
|||
type: 'ir.actions.act_window', |
|||
res_model: 'user.weather.map.config', |
|||
view_mode: 'form', |
|||
target:'inline', |
|||
views: [[false, 'form']], |
|||
}; |
|||
this.do_action(action); |
|||
}, |
|||
|
|||
on_click_weather_board: function (event) { |
|||
this.render_widget(); |
|||
}, |
|||
|
|||
}); |
|||
|
|||
SystrayMenu.Items.push(weather_menu); |
|||
}); |
@ -0,0 +1,120 @@ |
|||
// Navbar icon and dropdown |
|||
.o_weather_navbar_item { |
|||
> a { |
|||
opacity: 1; |
|||
float: left; |
|||
> i { |
|||
font-size: larger; |
|||
} |
|||
|
|||
} |
|||
|
|||
&.open .o_weather_navbar_dropdown { |
|||
.o-flex-display(); |
|||
.o-flex-flow(column, nowrap); |
|||
} |
|||
.weather_board{ |
|||
width: auto; |
|||
float: left; |
|||
font-size: 16px; |
|||
text-align:right; |
|||
} |
|||
.o_weather_navbar_dropdown { |
|||
width: 310px; |
|||
padding: 0; |
|||
|
|||
.o_spinner { |
|||
.o-flex-display(); |
|||
.o-align-items(center); |
|||
.o-justify-content(center); |
|||
color: @odoo-main-text-color; |
|||
height: 50px; |
|||
} |
|||
|
|||
.o_mail_navbar_dropdown_top { |
|||
.o-flex-display(); |
|||
.o-flex(0, 0, auto); |
|||
justify-content: space-between; |
|||
border-bottom: 1px solid lightgray; |
|||
|
|||
.o_filter_button, .o_new_message { |
|||
.btn-link; |
|||
padding: 5px; |
|||
} |
|||
.o_filter_button { |
|||
color: @odoo-main-color-muted; |
|||
&:hover, &.o_selected { |
|||
color: @odoo-brand-optional; |
|||
} |
|||
&.o_selected { |
|||
cursor: default; |
|||
font-weight: bold; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.o_mail_navbar_dropdown_channels { |
|||
.o-flex(0, 1, auto); |
|||
max-height: 400px; |
|||
min-height: 50px; |
|||
overflow-y: auto; |
|||
|
|||
@media (max-width: @screen-xs-max) { |
|||
max-height: none; |
|||
} |
|||
|
|||
.o_mail_channel_preview { |
|||
.o-flex-display(); |
|||
height: 50px; |
|||
align-items: center; |
|||
padding: 5px; |
|||
cursor: pointer; |
|||
font-size: 12px; |
|||
overflow: hidden; |
|||
&~.o_mail_channel_preview { |
|||
border-top: 1px solid lightgray; |
|||
} |
|||
&.o_channel_unread { |
|||
background-color: lighten(lightgray, 10%); |
|||
} |
|||
&:hover { |
|||
background-color: lighten(lightgray, 5%); |
|||
} |
|||
|
|||
.o_channel_image { |
|||
.o-flex(0, 0, 36px); |
|||
max-height: 36px; |
|||
} |
|||
.o_channel_info { |
|||
.o-flex(1, 1, 100%); |
|||
margin-left: 5px; |
|||
overflow: hidden; |
|||
|
|||
.o_channel_title { |
|||
.o-flex-display(); |
|||
.o_channel_name { |
|||
.o-flex(1, 1, auto); |
|||
.o-text-overflow(); |
|||
color: @odoo-main-text-color; |
|||
} |
|||
.o_last_message_date { |
|||
.o-flex(0, 0, auto); |
|||
padding-top: 3px; |
|||
font-size: xx-small; |
|||
color: @odoo-main-color-muted; |
|||
} |
|||
} |
|||
.o_last_message_preview { |
|||
width: 100%; |
|||
color: @odoo-main-color-muted; |
|||
.o-text-overflow(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
.o_no_chat_window .o_mail_navbar_dropdown .o_new_message { |
|||
display: none; // hide 'new message' button if chat windows are disabled |
|||
} |
@ -0,0 +1,95 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<templates xml:space="preserve"> |
|||
<t t-name="user_weather_map.weather_menu"> |
|||
<li class="o_weather_navbar_item"> |
|||
<a class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false" href="#" title="Weather"> |
|||
<div class="weather_board"><i class="fa fa-fw fa-cloud"/></div> |
|||
</a> |
|||
|
|||
<ul class="o_weather_navbar_dropdown dropdown-menu" role="menu"> |
|||
<li class="o_weather_navbar_dropdown_top"> |
|||
<div class="weather_notification"/> |
|||
</li> |
|||
</ul> |
|||
</li> |
|||
</t> |
|||
|
|||
<t t-name="WeatherDetails"> |
|||
<div class="weather_notification"> |
|||
<div> |
|||
<div class="weather_settings"> |
|||
<a title="Sign up" href="http://home.openweathermap.org/users/sign_up"> |
|||
<i class="fa fa-fw fa-sign-in"/> |
|||
</a> |
|||
<i title="Settings" class="fa fa-fw fa-cog"/> |
|||
</div> |
|||
</div> |
|||
<div class="weather_content"> |
|||
<div class="col-md-8"> |
|||
<t t-if="date_now"> |
|||
<p> |
|||
<t t-raw="date_now"/> |
|||
</p> |
|||
</t> |
|||
<t t-if="! issue"> |
|||
<t t-if="max_temp"> |
|||
<t t-if="min_temp"> |
|||
<p>Day <t t-raw="max_temp"/>° <i class="fa fa-long-arrow-up" aria-hidden="true"></i>, |
|||
Night <t t-raw="min_temp"/>° <i class="fa fa-long-arrow-down" aria-hidden="true"></i> |
|||
</p> |
|||
</t> |
|||
</t> |
|||
<t t-if="temp"> |
|||
<h1><t t-raw="temp"/>° <t t-if="weather"><t t-raw="weather"/></t></h1> |
|||
</t> |
|||
<t t-if="description"> |
|||
<p><t t-raw="description"/> <t t-if="name"> in <t t-raw="name"/></t></p> |
|||
</t> |
|||
<t t-if="city"> |
|||
<p>Near &nbsp;<t t-raw="city"/></p> |
|||
</t> |
|||
<t t-if="date_weather_update"> |
|||
last update:<p><t t-raw="date_weather_update"/></p> |
|||
</t> |
|||
</t> |
|||
<!--********************IF you need you can show the pressure,humidity etc.********************--> |
|||
</div> |
|||
|
|||
<t t-if="! issue"> |
|||
<div class="col-md-4" style="padding-top: 6%;padding-left: 0px;"> |
|||
<t t-if="weather =='Clouds'"> |
|||
<img src="/user_weather_map/static/src/img/cloud.png"></img> |
|||
</t> |
|||
<t t-if="weather =='Rain'"> |
|||
<img src="/user_weather_map/static/src/img/rain.png"></img> |
|||
</t> |
|||
<t t-if="weather =='Clear'"> |
|||
<img src="/user_weather_map/static/src/img/sun.png"></img> |
|||
</t> |
|||
<t t-if="weather =='Haze'"> |
|||
<img src="/user_weather_map/static/src/img/haze.png"></img> |
|||
</t> |
|||
<t t-if="weather =='Mist'"> |
|||
<img src="/user_weather_map/static/src/img/mist.png"></img> |
|||
</t> |
|||
<t t-if="weather =='Snow'"> |
|||
<img src="/user_weather_map/static/src/img/snow.png"></img> |
|||
</t> |
|||
<t t-if="weather =='Extreme'"> |
|||
<img src="/user_weather_map/static/src/img/haze.png"></img> |
|||
</t> |
|||
</div> |
|||
</t> |
|||
|
|||
<t t-if="issue"> |
|||
<div class="col-md-8 warning" style="padding-top: 6%;padding-left: 0px;"> |
|||
<h4><t t-raw="issue"/></h4> |
|||
</div> |
|||
<div class="col-md-4" style="padding-top: 0%;padding-left: 0px;"> |
|||
<img src="/user_weather_map/static/src/img/cloud-warning.png"></img> |
|||
</div> |
|||
</t> |
|||
</div> |
|||
</div> |
|||
</t> |
|||
</templates> |
@ -0,0 +1,49 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<data> |
|||
<record id="action_weather_conf_form" model="ir.ui.view"> |
|||
<field name="name">user.weather.map.conf.form</field> |
|||
<field name="model">user.weather.map.config</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Configure Weather" class="oe_form_configuration"> |
|||
<header> |
|||
<button string="Apply" type="object" name="execute_weather" class="oe_highlight"/> |
|||
</header> |
|||
<separator string="Weather" groups="base.group_user"/> |
|||
<group name="Weather" groups="base.group_user"> |
|||
<group> |
|||
<field name="user_id" /> |
|||
<field name="method" widget="radio"/> |
|||
<label for="street" string="Address"/> |
|||
<div> |
|||
<field name="street" placeholder="Street..." /> |
|||
<div class="address_format"> |
|||
<field name="city" placeholder="City" style="width: 40%" /> |
|||
<field name="state_id" class="oe_no_button" placeholder="State" style="width: 37%" options="{"no_open": True}" on_change="onchange_state(state_id)" domain="[('country_id','=',country_id)]" /> |
|||
<field name="zip" placeholder="ZIP" style="width: 20%" /> |
|||
</div> |
|||
<field name="country_id" placeholder="Country" class="oe_no_button" options="{"no_open": True}" /> |
|||
</div> |
|||
<field name="appid" /> |
|||
</group> |
|||
|
|||
<group> |
|||
<group colspan="2" col="2"> |
|||
<separator string="Geo Localization" colspan="2"/> |
|||
<field name="u_longitude" attrs="{'required':[('method','!=','address')]}"/> |
|||
<field name="u_latitude" attrs="{'required':[('method','!=','address')]}"/> |
|||
</group> |
|||
</group> |
|||
</group> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="action_weather_config" model="ir.actions.act_window"> |
|||
<field name="name">Weather Settings</field> |
|||
<field name="res_model">user.weather.map.config</field> |
|||
<field name="view_mode">form</field> |
|||
<field name="target">inline</field> |
|||
</record> |
|||
</data> |
|||
</odoo> |
@ -0,0 +1,12 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
<template id="assets_backend" name="mail assets" inherit_id="web.assets_backend"> |
|||
<xpath expr="." position="inside"> |
|||
<link rel="stylesheet" href="/user_weather_map/static/src/css/notification.css"/> |
|||
<link rel="stylesheet" href="/user_weather_map/static/src/less/weather.less"/> |
|||
<script type="text/javascript" src="/user_weather_map/static/src/js/weather_notification.js"/> |
|||
</xpath> |
|||
</template> |
|||
</data> |
|||
</openerp> |