[ADD] web_settings_dashboard: Settings Dashboard
This commit is contained in:
committed by
David Monjoie
parent
bd0c6a2b24
commit
c6a0af45ef
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import controllers
|
||||
import models
|
||||
@@ -0,0 +1,24 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
'name': 'Odoo Settings Dashboard',
|
||||
'version': '1.0',
|
||||
'summary': 'Quick actions for installing new app, adding users, completing planners, etc.',
|
||||
'category': 'Tools',
|
||||
'description':
|
||||
"""
|
||||
Odoo dashboard
|
||||
==============
|
||||
* Quick access to install apps
|
||||
* Quick users add
|
||||
* Access all planners at one place
|
||||
* Quick access to the `App Store` and `Theme Store`
|
||||
|
||||
""",
|
||||
'data': [
|
||||
'views/dashboard_views.xml',
|
||||
'views/dashboard_templates.xml',
|
||||
],
|
||||
'depends': ['web_planner'],
|
||||
'qweb': ['static/src/xml/dashboard.xml'],
|
||||
'auto_install': True,
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import main
|
||||
@@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openerp import http
|
||||
from openerp.http import request
|
||||
|
||||
|
||||
class WebSettingsDashboard(http.Controller):
|
||||
|
||||
@http.route('/web_settings_dashboard/data', type='json', auth='user')
|
||||
def web_settings_dashboard_data(self, **kw):
|
||||
|
||||
installed_apps = request.env['ir.module.module'].search_count([
|
||||
('application', '=', True),
|
||||
('state', 'in', ['installed', 'to upgrade', 'to remove'])
|
||||
])
|
||||
active_users = request.env['res.users'].search_count([('active', '=', True), ('login_date', '!=', False)])
|
||||
pending_users = request.env['res.users'].search([('login_date', '=', False)], order="create_date desc")
|
||||
|
||||
return {
|
||||
'apps': {
|
||||
'installed_apps': installed_apps
|
||||
},
|
||||
'users_info': {
|
||||
'active_users': active_users,
|
||||
'pending_users': zip(pending_users.mapped('id'), pending_users.mapped('login')),
|
||||
'user_form_view_id': request.env['ir.model.data'].xmlid_to_res_id("base.view_users_form"),
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import res_users
|
||||
@@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from openerp import models, api, _
|
||||
from openerp.exceptions import RedirectWarning
|
||||
from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
|
||||
|
||||
|
||||
class Users(models.Model):
|
||||
_inherit = 'res.users'
|
||||
|
||||
@api.model
|
||||
def web_dashboard_create_users(self, emails):
|
||||
|
||||
# Reactivate already existing users if needed
|
||||
deactivated_users = self.with_context(active_test=False).search([('active', '=', False), '|', ('login', 'in', emails), ('email', 'in', emails)])
|
||||
for user in deactivated_users:
|
||||
user.active = True
|
||||
|
||||
new_emails = set(emails) - set(deactivated_users.mapped('email'))
|
||||
|
||||
# Process new email addresses : create new users
|
||||
for email in new_emails:
|
||||
default_values = {'login': email, 'name': email.split('@')[0], 'email': email, 'active': True}
|
||||
user = self.create(default_values)
|
||||
|
||||
return True
|
||||
@@ -0,0 +1,266 @@
|
||||
odoo.define('web_settings_dashboard', function (require) {
|
||||
"use strict";
|
||||
|
||||
var core = require('web.core');
|
||||
var Widget = require('web.Widget');
|
||||
var Model = require('web.Model');
|
||||
var session = require('web.session');
|
||||
var PlannerCommon = require('web.planner.common');
|
||||
var framework = require('web.framework');
|
||||
var webclient = require('web.web_client');
|
||||
var PlannerDialog = PlannerCommon.PlannerDialog;
|
||||
|
||||
var QWeb = core.qweb;
|
||||
var _t = core._t;
|
||||
|
||||
var Dashboard = Widget.extend({
|
||||
template: 'DashboardMain',
|
||||
|
||||
events: {
|
||||
'click .o_browse_apps': 'on_new_apps',
|
||||
},
|
||||
|
||||
start: function(){
|
||||
return this.load(['apps', 'invitations', 'planner', 'share'])
|
||||
},
|
||||
|
||||
load: function(dashboards){
|
||||
var self = this;
|
||||
var loading_done = new $.Deferred();
|
||||
session.rpc("/web_settings_dashboard/data", {}).then(function (data) {
|
||||
// Load each dashboard
|
||||
var all_dashboards_defs = []
|
||||
_.each(dashboards, function(dashboard) {
|
||||
var dashboard_def = self['load_' + dashboard](data);
|
||||
if (dashboard_def) {
|
||||
all_dashboards_defs.push(dashboard_def);
|
||||
}
|
||||
});
|
||||
|
||||
// Resolve loading_done when all dashboards defs are resolved
|
||||
$.when.apply($, all_dashboards_defs).then(function() {
|
||||
loading_done.resolve();
|
||||
});
|
||||
});
|
||||
return loading_done;
|
||||
},
|
||||
|
||||
load_apps: function(data){
|
||||
this.$('.o_web_settings_dashboard_apps').append(QWeb.render("DashboardApps", data['apps']));
|
||||
},
|
||||
|
||||
load_share: function(data){
|
||||
return new DashboardShare(this, {}).replace(this.$('.o_web_settings_dashboard_share'));
|
||||
},
|
||||
|
||||
load_invitations: function(data){
|
||||
return new DashboardInvitations(this, data['users_info']).replace(this.$('.o_web_settings_dashboard_invitations'));
|
||||
},
|
||||
|
||||
load_planner: function(data){
|
||||
return new DashboardPlanner(this, data['planner']).replace(this.$('.o_web_settings_dashboard_planner'));
|
||||
},
|
||||
|
||||
on_new_apps: function(){
|
||||
this.do_action('base.open_module_tree');
|
||||
}
|
||||
});
|
||||
|
||||
var DashboardInvitations = Widget.extend({
|
||||
template: 'DashboardInvitations',
|
||||
events: {
|
||||
'click .o_web_settings_dashboard_invitations': 'send_invitations',
|
||||
'click .o_web_settings_dashboard_access_rights': 'on_access_rights_clicked',
|
||||
'click .o_web_settings_dashboard_user': 'on_user_clicked',
|
||||
},
|
||||
init: function(parent, data){
|
||||
this.data = data;
|
||||
this.parent = parent;
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
send_invitations: function(e){
|
||||
var self = this;
|
||||
var $target = $(e.currentTarget);
|
||||
var user_emails = _.filter(this.$('#user_emails').val().split(/[\n, ]/), function(email){
|
||||
return email != "";
|
||||
});
|
||||
var re = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
|
||||
var is_valid_emails = _.every(user_emails, function(email) {
|
||||
return re.test(email);
|
||||
});
|
||||
if (is_valid_emails) {
|
||||
// Disable button
|
||||
$target.prop('disabled', true);
|
||||
$target.find('i.fa-cog').removeClass('hidden');
|
||||
// Try to create user accountst
|
||||
new Model("res.users")
|
||||
.call("web_dashboard_create_users", [user_emails])
|
||||
.then(function() {
|
||||
self.reload();
|
||||
})
|
||||
.always(function() {
|
||||
// Re-enable button
|
||||
self.$('.o_web_settings_dashboard_invitations').prop('disabled', false);
|
||||
self.$('i.fa-cog').addClass('hidden');
|
||||
});
|
||||
|
||||
}
|
||||
else {
|
||||
this.do_warn(_t("Please provide valid email addresses"), "");
|
||||
}
|
||||
},
|
||||
on_access_rights_clicked: function (e) {
|
||||
var self = this;
|
||||
e.preventDefault();
|
||||
this.do_action('base.action_res_users', {
|
||||
on_reverse_breadcrumb: function(){ return self.reload();}
|
||||
});
|
||||
},
|
||||
on_user_clicked: function (e) {
|
||||
var self = this;
|
||||
e.preventDefault();
|
||||
var user_id = $(e.currentTarget).data('user-id');
|
||||
var action = {
|
||||
type: 'ir.actions.act_window',
|
||||
view_type: 'form',
|
||||
view_mode: 'form',
|
||||
res_model: 'res.users',
|
||||
views: [[this.data.user_form_view_id, 'form']],
|
||||
res_id: user_id,
|
||||
}
|
||||
this.do_action(action,{
|
||||
on_reverse_breadcrumb: function(){ return self.reload();}
|
||||
});
|
||||
},
|
||||
reload:function(){
|
||||
return this.parent.load(['invitations']);
|
||||
},
|
||||
});
|
||||
|
||||
var DashboardPlanner = Widget.extend({
|
||||
|
||||
template: 'DashboardPlanner',
|
||||
|
||||
events: {
|
||||
'click .o_web_settings_dashboard_progress_title,.progress': 'on_planner_clicked',
|
||||
},
|
||||
|
||||
init: function(parent, data){
|
||||
this.data = data;
|
||||
this.parent = parent;
|
||||
this.planner_by_menu = {};
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
willStart:function(){
|
||||
var self = this;
|
||||
return new Model('web.planner').query().all().then(function(res) {
|
||||
self.planners = res;
|
||||
_.each(self.planners, function(planner) {
|
||||
self.planner_by_menu[planner.menu_id[0]] = planner;
|
||||
self.planner_by_menu[planner.menu_id[0]].data = $.parseJSON(planner.data) || {};
|
||||
});
|
||||
self.set_overall_progress();
|
||||
});
|
||||
},
|
||||
|
||||
update_planner_progress: function(){
|
||||
this.set_overall_progress();
|
||||
this.$('.o_web_settings_dashboard_planners_list').replaceWith(
|
||||
QWeb.render("DashboardPlanner.PlannersList", {'planners': this.planners})
|
||||
);
|
||||
},
|
||||
|
||||
set_overall_progress: function(){
|
||||
var self = this;
|
||||
this.sort_planners_list();
|
||||
var average = _.reduce(self.planners, function(memo, planner) {
|
||||
return planner.progress + memo;
|
||||
}, 0) / (self.planners.length || 1);
|
||||
self.overall_progress = Math.floor(average);
|
||||
self.$('.o_web_settings_dashboard_planner_overall_progress').text(self.overall_progress);
|
||||
},
|
||||
|
||||
sort_planners_list: function(){
|
||||
// sort planners alphabetically but with fully completed planners at the end:
|
||||
this.planners = _.sortBy(this.planners, function(planner){return (planner.progress == 100) + planner.name});
|
||||
},
|
||||
|
||||
on_planner_clicked: function(e){
|
||||
|
||||
var menu_id = $(e.currentTarget).attr('data-menu-id');
|
||||
// Setup the planner if we didn't do it yet
|
||||
if (this.planner && this.planner.menu_id[0] == menu_id) {
|
||||
this.dialog.$el.modal('show');
|
||||
}
|
||||
else {
|
||||
this.setup_planner(menu_id);
|
||||
}
|
||||
},
|
||||
|
||||
setup_planner: function(menu_id){
|
||||
var self = this;
|
||||
this.planner = self.planner_by_menu[menu_id];
|
||||
if (this.dialog) {
|
||||
this.dialog.destroy()
|
||||
}
|
||||
this.dialog = new PlannerDialog(this, this.planner);
|
||||
this.dialog.on("planner_progress_changed", this, function(percent) {
|
||||
self.planner.progress = percent;
|
||||
self.update_planner_progress();
|
||||
});
|
||||
this.dialog.appendTo(webclient.$el).then(function() {
|
||||
self.dialog.$el.modal('show');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var DashboardShare = Widget.extend({
|
||||
template: 'DashboardShare',
|
||||
|
||||
events: {
|
||||
'click .tw_share': 'share_twitter',
|
||||
'click .fb_share': 'share_facebook',
|
||||
'click .li_share': 'share_linkedin',
|
||||
},
|
||||
|
||||
init: function(parent, data){
|
||||
this.data = data;
|
||||
this.parent = parent;
|
||||
this.share_url = 'http://www.odoo.com/';
|
||||
this.share_text = encodeURIComponent("#IamUsingOdoo, an Open-Source Web App that manages my Sales, Projects, Accounting, Website, Warehouse, Shop and more");
|
||||
},
|
||||
|
||||
share_twitter: function(){
|
||||
var popup_url = _.str.sprintf( 'https://twitter.com/intent/tweet?tw_p=tweetbutton&text=%s %s',this.share_text,this.share_url);
|
||||
this.sharer(popup_url);
|
||||
},
|
||||
|
||||
share_facebook: function(){
|
||||
var popup_url = _.str.sprintf('https://www.facebook.com/sharer/sharer.php?u=%s', encodeURIComponent(this.share_url));
|
||||
this.sharer(popup_url);
|
||||
},
|
||||
|
||||
share_linkedin: function(){
|
||||
var popup_url = _.str.sprintf('http://www.linkedin.com/shareArticle?mini=true&url=%s&title=I am using odoo&summary=%s&source=www.odoo.com', encodeURIComponent(this.share_url), this.share_text);
|
||||
this.sharer(popup_url);
|
||||
},
|
||||
|
||||
sharer: function(popup_url){
|
||||
window.open(
|
||||
popup_url,
|
||||
'Share Dialog',
|
||||
'width=600,height=400'); // We have to add a size otherwise the window pops in a new tab
|
||||
}
|
||||
});
|
||||
|
||||
core.action_registry.add('web_settings_dashboard.main', Dashboard);
|
||||
|
||||
return {
|
||||
Dashboard: Dashboard,
|
||||
DashboardInvitations: DashboardInvitations,
|
||||
DashboardPlanner: DashboardPlanner,
|
||||
DashboardShare: DashboardShare,
|
||||
};
|
||||
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
.o_web_settings_dashboard {
|
||||
|
||||
@bg-dashboard-col: #FFF;
|
||||
|
||||
.o_web_settings_dashboard_card() {
|
||||
box-shadow: 0 1px 2px 0 rgba(0,0,0,.14);
|
||||
background: @bg-dashboard-col;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
background: #F7F7F7;
|
||||
height: 100%;
|
||||
|
||||
.o_web_settings_dashboard_col {
|
||||
padding: 10px 8px;
|
||||
|
||||
> div > hr {
|
||||
margin: 12px -18px 15px -18px;
|
||||
border-color: #CBCBCB;
|
||||
}
|
||||
|
||||
> div:first-child {
|
||||
.o_web_settings_dashboard_card();
|
||||
padding: 25px 18px 18px 18px;
|
||||
.o_web_settings_dashboard_header {
|
||||
font-size: 22px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
.o_web_settings_dashboard_pills {
|
||||
margin-top: 10px;
|
||||
|
||||
> li > a {
|
||||
.o_web_settings_dashboard_card();
|
||||
padding: 10px;
|
||||
|
||||
> i.fa {
|
||||
vertical-align: middle;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
}
|
||||
@media (max-width: 1200px) {
|
||||
> li {
|
||||
width: 100%;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn.o_browse_apps, .btn.o_web_settings_dashboard_invitations {
|
||||
margin-top: 12px;
|
||||
}
|
||||
.o_web_settings_dashboard_compact_subtitle {
|
||||
line-height: 12px;
|
||||
display: block;
|
||||
}
|
||||
.o_web_settings_dashboard_invitations {
|
||||
.o_web_settings_dashboard_invitation_form {
|
||||
text-align: left;
|
||||
> textarea {
|
||||
resize: vertical;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
a.o_web_settings_dashboard_user {
|
||||
line-height: 24px;
|
||||
}
|
||||
}
|
||||
.o_web_settings_dashboard_planner {
|
||||
.progress {
|
||||
height: 10px;
|
||||
background-color: darken(@bg-dashboard-col, 15%);
|
||||
cursor: pointer;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
.o_web_settings_dashboard_planner_progress_text {
|
||||
font-size: 18px;
|
||||
padding-right: 0px;
|
||||
padding-top: 3px;
|
||||
}
|
||||
.o_web_settings_dashboard_planner_progress_bar {
|
||||
padding-left: 10px;
|
||||
}
|
||||
.o_web_settings_dashboard_progress_title {
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
color: @odoo-brand-optional;
|
||||
}
|
||||
.o_web_settings_dashboard_progress_100 {
|
||||
-webkit-filter: grayscale(100%);
|
||||
filter: grayscale(100%);
|
||||
&.o_web_settings_dashboard_planner_progress_text {
|
||||
font-size: 15px
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<templates xml:space="preserve">
|
||||
<t t-name="DashboardMain">
|
||||
<div class="container-fluid o_web_settings_dashboard">
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-sm-6 col-xs-12 o_web_settings_dashboard_col"> <div class="text-center o_web_settings_dashboard_apps"></div>
|
||||
<ul class="nav nav-pills o_web_settings_dashboard_pills">
|
||||
<li role="presentation" class="text-center"><a href="https://www.odoo.com/apps/modules" target="_blank"><i class="fa fa-rocket fa-2x text-muted"/> App store </a></li>
|
||||
<li role="presentation" class="text-center pull-right"><a href="https://www.odoo.com/apps/themes" target="_blank"><i class="fa fa-picture-o fa-2x text-muted"/> Theme store</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-3 col-sm-6 col-xs-12 o_web_settings_dashboard_col">
|
||||
<div class="text-center o_web_settings_dashboard_invitations"></div>
|
||||
</div>
|
||||
<div class="col-md-3 col-sm-6 col-xs-12 o_web_settings_dashboard_col">
|
||||
<div class="text-center o_web_settings_dashboard_planner"></div>
|
||||
</div>
|
||||
<div class="col-md-3 col-sm-6 col-xs-12 o_web_settings_dashboard_col">
|
||||
<div class="text-center o_web_settings_dashboard_share"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="DashboardApps">
|
||||
<i class="fa fa-cog fa-4x text-muted"></i>
|
||||
<div class="o_web_settings_dashboard_header">
|
||||
<t t-if="installed_apps">
|
||||
<t t-esc="installed_apps"></t>
|
||||
<t t-if="installed_apps == 1">Installed App</t>
|
||||
<t t-if="installed_apps > 1">Installed Apps</t>
|
||||
</t>
|
||||
<t t-if="! installed_apps">
|
||||
No app installed
|
||||
</t>
|
||||
</div>
|
||||
<div>
|
||||
<a class="btn btn-primary btn-block o_browse_apps" role="button"><strong>Browse Apps</strong></a>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="DashboardInvitations">
|
||||
<div class="text-center o_web_settings_dashboard_invitations">
|
||||
<i class="fa fa-users fa-4x text-muted"></i>
|
||||
<div class="o_web_settings_dashboard_header">
|
||||
<t t-set="active_users" t-value="widget.data.active_users"></t>
|
||||
<t t-set="pending_users" t-value="widget.data.pending_users"></t>
|
||||
<t t-if="active_users">
|
||||
<t t-esc="active_users"></t> Active User<t t-if="active_users > 1">s</t>
|
||||
</t>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<a href="#" class="o_web_settings_dashboard_access_rights"> Manage access rights</a>
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="o_web_settings_dashboard_invitation_form">
|
||||
<strong>Add new users</strong> <small class="text-muted">(with default rights)</small>
|
||||
<textarea rows="3" id="user_emails" placeholder="Enter e-mail addresses"></textarea>
|
||||
<button class="btn btn-primary btn-block o_web_settings_dashboard_invitations" role="button"> <strong><i class="fa fa-cog fa-spin hidden"/> Add Users</strong></button>
|
||||
</div>
|
||||
<div>
|
||||
<small class="o_web_settings_dashboard_pending_users text-muted text-center">
|
||||
<t t-if="pending_users.length">
|
||||
<br/>
|
||||
<strong>Pending users:</strong><br/>
|
||||
<t t-foreach="pending_users" t-as="pending">
|
||||
<a href="#"><div class="o_web_settings_dashboard_user" t-att-data-user-id="pending[0]"> <t t-esc="pending[1]"/></div></a>
|
||||
</t>
|
||||
</t>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="DashboardPlanner">
|
||||
<div class="text-center o_web_settings_dashboard_planner">
|
||||
<i class="fa fa-info-circle fa-4x text-muted"></i>
|
||||
<div class="o_web_settings_dashboard_header">
|
||||
<span class="o_web_settings_dashboard_planner_overall_progress"><t t-esc="widget.overall_progress"></t></span>%
|
||||
Implementation
|
||||
</div>
|
||||
<div>
|
||||
<small class="text-muted text-center o_web_settings_dashboard_compact_subtitle">
|
||||
Follow these Implementation Guides to get the maximum value for your business.
|
||||
</small>
|
||||
</div>
|
||||
<hr/>
|
||||
<t t-set="planners" t-value="widget.planners"/>
|
||||
<t t-call="DashboardPlanner.PlannersList"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="DashboardPlanner.PlannersList">
|
||||
<div class="row o_web_settings_dashboard_planners_list">
|
||||
<t t-if="!planners.length">
|
||||
<div>You need to install some apps first.</div>
|
||||
</t>
|
||||
<t t-if="planners.length" t-foreach="planners" t-as="p">
|
||||
<div t-attf-class="col-xs-2 col-md-3 col-lg-2 o_web_settings_dashboard_planner_progress_text o_web_settings_dashboard_progress_#{p.progress}">
|
||||
<t t-esc="p.progress"/>%
|
||||
</div>
|
||||
<div t-attf-class="col-xs-10 col-md-9 col-lg-10 o_web_settings_dashboard_planner_progress_bar o_web_settings_dashboard_progress_#{p.progress}">
|
||||
<div class="o_web_settings_dashboard_progress_title text-left" t-att-data-menu-id="p.menu_id[0]">
|
||||
<t t-esc="p.menu_id[1]"></t> <i class="fa fa-arrow-right pull-right"/>
|
||||
</div>
|
||||
<div class="progress" t-att-data-menu-id="p.menu_id[0]">
|
||||
<div class="progress-bar" role="progressbar" t-attf-style="width:#{p.progress}%">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="DashboardShare">
|
||||
<div class="text-center o_web_settings_dashboard_share">
|
||||
<i class="fa fa-share-alt fa-4x text-muted"/>
|
||||
<div class="o_web_settings_dashboard_header">Social Share</div>
|
||||
<div>
|
||||
<small class="text-muted text-center o_web_settings_dashboard_compact_subtitle">
|
||||
Help us spread the word: Share Odoo's awesomeness with your friends!
|
||||
</small>
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="row mt16">
|
||||
<div class="col-xs-4"><a><i class="fa fa-twitter-square fa-4x tw_share"/></a></div>
|
||||
<div class="col-xs-4"><a><i class="fa fa-facebook-square fa-4x fb_share"/></a></div>
|
||||
<div class="col-xs-4"><a><i class="fa fa-linkedin-square fa-4x li_share"/></a></div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<template id="assets_backend" name="Web Settings Dashboard Assets" inherit_id="web.assets_backend" priority="17">
|
||||
<xpath expr="." position="inside">
|
||||
<link href="/web_settings_dashboard/static/src/less/dashboard.less" rel="stylesheet" type="text/less"/>
|
||||
<script type="text/javascript" src="/web_settings_dashboard/static/src/js/dashboard.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</odoo>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="web_settings_dashboard_action" model="ir.actions.client">
|
||||
<field name="name">Dashboard</field>
|
||||
<field name="tag">web_settings_dashboard.main</field>
|
||||
</record>
|
||||
<menuitem name="Dashboard" id="web_dashboard_menu" action="web_settings_dashboard_action" parent="base.menu_administration" sequence="-1" />
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user