上传修改后的主题
This commit is contained in:
18
spiffy_theme_backend/static/src/js/SpiffyPageTitle.js
Normal file
18
spiffy_theme_backend/static/src/js/SpiffyPageTitle.js
Normal file
@@ -0,0 +1,18 @@
|
||||
odoo.define('spiffy_theme_backend.SpiffyPageTitle', function (require) {
|
||||
"use strict";
|
||||
|
||||
var ajax = require('web.ajax');
|
||||
var { WebClient } = require("@web/webclient/webclient");
|
||||
var { patch } = require("web.utils");
|
||||
|
||||
patch(WebClient.prototype, "spiffy_theme_backend.SpiffyPageTitle", {
|
||||
setup() {
|
||||
this._super();
|
||||
var self = this
|
||||
ajax.rpc('/get/tab/title/').then(function(rec) {
|
||||
var new_title = rec
|
||||
self.title.setParts({ zopenerp: new_title })
|
||||
})
|
||||
},
|
||||
});
|
||||
});
|
||||
32
spiffy_theme_backend/static/src/js/SwitchCompanyMenu.js
Normal file
32
spiffy_theme_backend/static/src/js/SwitchCompanyMenu.js
Normal file
@@ -0,0 +1,32 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
var config = require('web.config');
|
||||
var core = require('web.core');
|
||||
var session = require('@web/session');
|
||||
var SystrayMenu = require('web.SystrayMenu');
|
||||
var Widget = require('web.Widget');
|
||||
var { patch } = require("web.utils");
|
||||
var { SwitchCompanyMenu } = require("@web/webclient/switch_company_menu/switch_company_menu");
|
||||
var { registry } = require("@web/core/registry");
|
||||
|
||||
var _t = core._t;
|
||||
|
||||
patch(SwitchCompanyMenu.prototype, "spiffy_theme_backend.SwitchCompanyMenu", {
|
||||
setup() {
|
||||
this._super();
|
||||
this.isDebug = config.isDebug();
|
||||
this.isAssets = config.isDebug("assets");
|
||||
this.isTests = config.isDebug("tests");
|
||||
},
|
||||
});
|
||||
|
||||
// show company menu even if company is count is 1
|
||||
const systrayItemSwitchCompanyMenu = {
|
||||
Component: SwitchCompanyMenu,
|
||||
isDisplayed(env) {
|
||||
const { availableCompanies } = env.services.company;
|
||||
return Object.keys(availableCompanies).length > 0;
|
||||
},
|
||||
};
|
||||
|
||||
registry.category("systray").add("SwitchCompanyMenu", systrayItemSwitchCompanyMenu, { sequence: 1, force: true });
|
||||
1623
spiffy_theme_backend/static/src/js/action_service.js
Normal file
1623
spiffy_theme_backend/static/src/js/action_service.js
Normal file
File diff suppressed because it is too large
Load Diff
407
spiffy_theme_backend/static/src/js/apps_menu.js
Normal file
407
spiffy_theme_backend/static/src/js/apps_menu.js
Normal file
@@ -0,0 +1,407 @@
|
||||
/** @odoo-module **/
|
||||
import {fuzzyLookup} from "@web/core/utils/search";
|
||||
var core = require('web.core');
|
||||
var qweb = core.qweb;
|
||||
var ajax = require('web.ajax');
|
||||
var { NavBar } = require("@web/webclient/navbar/navbar");
|
||||
var { patch } = require("web.utils");
|
||||
const { useListener } = require("@web/core/utils/hooks");
|
||||
const {useRef, useState } = owl;
|
||||
import { browser } from "@web/core/browser/browser";
|
||||
import body_color from "spiffy_theme_backend.MenuJs";
|
||||
|
||||
function AppDrawerfindNames(memo, menu) {
|
||||
if (menu.action) {
|
||||
var key = menu.parent_id ? menu.parent_id[1] + "/" : "";
|
||||
memo[key + menu.name] = menu;
|
||||
}
|
||||
if (menu.children) {
|
||||
_.reduce(menu.children, AppDrawerfindNames, memo);
|
||||
}
|
||||
return memo;
|
||||
}
|
||||
|
||||
function findNames(memo, menu) {
|
||||
if (menu.actionID) {
|
||||
memo[menu.name.trim()] = menu;
|
||||
}
|
||||
if (menu.childrenTree) {
|
||||
const innerMemo = _.reduce(menu.childrenTree, findNames, {});
|
||||
for (const innerKey in innerMemo) {
|
||||
memo[menu.name.trim() + " / " + innerKey] = innerMemo[innerKey];
|
||||
}
|
||||
}
|
||||
return memo;
|
||||
}
|
||||
|
||||
export function divertColorItem(env) {
|
||||
const route = "/primary_color/divertable_color";
|
||||
return {
|
||||
type: "item",
|
||||
id: "divert.account",
|
||||
description: env._t("Switch/Add Account"),
|
||||
href: `${browser.location.origin}${route}`,
|
||||
callback: () => {
|
||||
body_color.methods.divertColor();
|
||||
},
|
||||
sequence: 70,
|
||||
};
|
||||
}
|
||||
|
||||
patch(NavBar.prototype, "spiffy_theme_backend.appsMenuJs", {
|
||||
setup() {
|
||||
this._super();
|
||||
|
||||
var self = this;
|
||||
$(document).on("keydown", "#app_menu_search", function(ev){self._AppsearchResultsNavigate(ev)});
|
||||
$(document).on("input", "#app_menu_search", function(ev){self._searchAppDrawerTimeout(ev)});
|
||||
$(document).on("click", "#search_result .search_list_content a", function(ev){self._ToggleDrawer(ev)});
|
||||
$(document).on("click", ".fav_app_select", function(ev){self._AddRemoveFavApps(ev)});
|
||||
$(document).on("click", ".appdrawer_section .app-box .o_app", function(ev){self._ToggleDrawer(ev)});
|
||||
|
||||
var menuData = this.menuService.getApps()
|
||||
|
||||
this._search_def = false;
|
||||
|
||||
this._GetFavouriteApps()
|
||||
// this._AppdrawerIcons()
|
||||
this._FavouriteAppsIsland()
|
||||
|
||||
this.state = useState({
|
||||
results: [],
|
||||
offset: 0,
|
||||
hasResults: false,
|
||||
});
|
||||
|
||||
this.searchBarInput = useRef("SearchBarInput");
|
||||
this._drawersearchableMenus = [];
|
||||
for (const menu of this.menuService.getApps()) {
|
||||
Object.assign(
|
||||
this._drawersearchableMenus,
|
||||
_.reduce([this.menuService.getMenuAsTree(menu.id)], findNames, {})
|
||||
);
|
||||
}
|
||||
$('.o_main_navbar').removeClass('d-none')
|
||||
|
||||
$('.favorite_apps_section').scroll(function(){
|
||||
if ($('.favorite_apps_section').scrollTop() > 20) {
|
||||
$('.favorite_apps_section').css( { height: `calc(100vh - ${sidebar_systray_height}px)` } );
|
||||
} else {
|
||||
$('.favorite_apps_section').css( { height: `calc(100vh - ${sidebar_systray_height}px)` } );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_ToggleDrawer: function (ev) {
|
||||
$('.o_main_navbar').toggleClass('appdrawer-toggle')
|
||||
$('.appdrawer_section').toggleClass('toggle')
|
||||
$('.o_app_drawer a').toggleClass('toggle')
|
||||
|
||||
// reset app drawer search details on drawer close
|
||||
if (!$('.appdrawer_section').hasClass('toggle')) {
|
||||
$("input[id='app_menu_search']").val("")
|
||||
$(".appdrawer_section #search_result").empty()
|
||||
$('.appdrawer_section .apps-list .row').removeClass('d-none');
|
||||
$('#searched_main_apps').empty().addClass('d-none').removeClass('d-flex');
|
||||
}
|
||||
},
|
||||
|
||||
_FavouriteAppsIsland: function (ev){
|
||||
if (this.favappsdata) {
|
||||
var rec = this.favappsdata
|
||||
if (rec.app_list.length) {
|
||||
$('.fav_app_island .fav_apps').empty();
|
||||
$.each(rec.app_list, function( index, value ) {
|
||||
if (value['web_icon'] != false){
|
||||
var web_icon_ext = value['web_icon'].split('/icon.')[1]
|
||||
var web_svg_src = value['web_icon'].replace(',', '/')
|
||||
}
|
||||
else {
|
||||
var web_icon_ext = value['web_icon'].toString()
|
||||
var web_svg_src = value['web_icon'].toString()
|
||||
}
|
||||
var favapps = $(qweb.render("FavoriteApps", {
|
||||
app_name:value['name'],
|
||||
app_id:value['app_id'],
|
||||
app_xmlid:value['app_xmlid'],
|
||||
app_actionid:value['app_actionid'],
|
||||
use_icon:value['use_icon'],
|
||||
icon_class_name:value['icon_class_name'],
|
||||
icon_img:value['icon_img'],
|
||||
web_icon: value['web_icon'],
|
||||
web_icon_data:value['web_icon_data'],
|
||||
web_icon_ext: web_icon_ext,
|
||||
web_svg_src: web_svg_src,
|
||||
}))
|
||||
$('.fav_app_island .fav_apps').append(favapps)
|
||||
});
|
||||
$('.fav_app_island').removeClass('d-none')
|
||||
} else {
|
||||
$('.fav_app_island').addClass('d-none')
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_GetFavouriteApps: function() {
|
||||
var apps = this.menuService.getApps()
|
||||
var self = this
|
||||
if (this.favappsdata) {
|
||||
var rec = this.favappsdata
|
||||
$.each(rec.app_list, function( index, value ) {
|
||||
$.each(apps, function( ind, val ) {
|
||||
if (value['app_id'] == val.id) {
|
||||
var target = ".o_app[data-menu-id="+val.id+"]";
|
||||
var $target = $(target);
|
||||
$target.parent().find('.fav_app_select .ri').addClass('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
ajax.rpc('/get-favorite-apps').then(function(rec) {
|
||||
if (rec) {
|
||||
self.favappsdata = rec
|
||||
$.each(rec.app_list, function( index, value ) {
|
||||
$.each(apps, function( ind, val ) {
|
||||
if (value['app_id'] == val.id) {
|
||||
var target = ".o_app[data-menu-id="+val.id+"]";
|
||||
var $target = $(target);
|
||||
$target.parent().find('.fav_app_select .ri').addClass('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
self._FavouriteAppsIsland()
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
get_user_data: function (ev) {
|
||||
var self = this
|
||||
var session = this.getSession();
|
||||
var $avatar = $('.user_image img');
|
||||
var avatar_src = session.url('/web/image', {
|
||||
model:'res.users',
|
||||
field: 'image_128',
|
||||
id: session.uid,
|
||||
});
|
||||
var value = {
|
||||
'avatar_src': avatar_src,
|
||||
'user_id': session.uid,
|
||||
'user_name': session.name,
|
||||
// 'greeting': greeting,
|
||||
}
|
||||
$avatar.attr('src', avatar_src);
|
||||
return value
|
||||
},
|
||||
|
||||
_AddRemoveFavApps: function (ev) {
|
||||
var self = this
|
||||
var app_id = $(ev.target).parent().find('.o_app').attr('data-menu-id')
|
||||
var app_name = $(ev.target).parent().find('.app-name').text()
|
||||
if ($(ev.target).find('.ri.active').length) {
|
||||
ajax.jsonRpc('/remove-user-fav-apps','call', {
|
||||
'app_id':app_id,
|
||||
}).then(function(rec) {
|
||||
$(ev.target).find('.ri').removeClass('active');
|
||||
self._FavouriteAppsIsland()
|
||||
});
|
||||
} else {
|
||||
ajax.jsonRpc('/update-user-fav-apps','call', {
|
||||
'app_name':app_name,
|
||||
'app_id':app_id,
|
||||
}).then(function(rec) {
|
||||
$(ev.target).find('.ri').addClass('active');
|
||||
self._FavouriteAppsIsland()
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_getsearchedapps: function(searchvals) {
|
||||
var self = this
|
||||
var apps = this.menuService.getApps()
|
||||
if (searchvals === "") {
|
||||
$('#searched_main_apps').empty().addClass('d-none').removeClass('d-flex');
|
||||
return;
|
||||
}
|
||||
$('#searched_main_apps').empty().addClass('d-flex').removeClass('d-none');
|
||||
$.each(apps, function( index, value ) {
|
||||
if(value['name'].toLowerCase().indexOf(searchvals.toLowerCase()) != -1){
|
||||
var searchapps = $(qweb.render("SearchedApps", {
|
||||
app_name:value['name'],
|
||||
app_id:value['menuID'],
|
||||
app_xmlid:value['xmlID'],
|
||||
app_actionid:value['actionID'],
|
||||
}))
|
||||
if (value['use_icon']) {
|
||||
if (value['icon_class_name']) {
|
||||
var icon_span = "<span class='ri "+value['icon_class_name']+"'/>"
|
||||
$(searchapps).find('.app-image').append($(icon_span))
|
||||
} else if (value['icon_img']) {
|
||||
var icon_image = "<img class='img img-fluid' src='/web/image/ir.ui.menu/"+value['id']+"/icon_img' />"
|
||||
$(searchapps).find('.app-image').append($(icon_image))
|
||||
} else if (value['webIconData'].toString() === 'false') {
|
||||
var icon_image = "<img class='img img-fluid' src='/spiffy_theme_backend/static/description/bizople-icon.png' />"
|
||||
$(searchapps).find('.app-image').append($(icon_image))
|
||||
} else {
|
||||
var icon_image = "<img class='img img-fluid use_icon' src='/web/image/ir.ui.menu/"+value['id']+"/web_icon_data' />"
|
||||
$(searchapps).find('.app-image').append($(icon_image))
|
||||
}
|
||||
} else {
|
||||
if (value['icon_img']) {
|
||||
var icon_image = "<img class='img img-fluid' src='/web/image/ir.ui.menu/"+value['id']+"/icon_img' />"
|
||||
$(searchapps).find('.app-image').append($(icon_image))
|
||||
} else if (value['webIconData'].toString() === 'false') {
|
||||
var icon_image = "<img class='img img-fluid' src='/spiffy_theme_backend/static/description/bizople-icon.png' />"
|
||||
$(searchapps).find('.app-image').append($(icon_image))
|
||||
} else {
|
||||
var icon_image = "<img class='img img-fluid else' src='/web/image/ir.ui.menu/"+value['id']+"/web_icon_data' />"
|
||||
$(searchapps).find('.app-image').append($(icon_image))
|
||||
}
|
||||
}
|
||||
$('.apps-list #searched_main_apps').append(searchapps);
|
||||
}
|
||||
});
|
||||
this._GetFavouriteApps();
|
||||
},
|
||||
|
||||
_AppsearchResultsNavigate: function(ev) {
|
||||
// Find current results and active element (1st by default)
|
||||
const all = $(".appdrawer_section #search_result").find(".search_list_content"),
|
||||
pre_focused = all.filter(".navigate_active") || $(all[0]);
|
||||
let offset = all.index(pre_focused),
|
||||
key = ev.key;
|
||||
// Keyboard navigation only supports search results
|
||||
if (!all.length) {
|
||||
return;
|
||||
}
|
||||
// Transform tab presses in arrow presses
|
||||
if (key === "Tab") {
|
||||
ev.preventDefault();
|
||||
key = ev.shiftKey ? "ArrowUp" : "ArrowDown";
|
||||
}
|
||||
switch (key) {
|
||||
// Pressing enter is the same as clicking on the active element
|
||||
case "Enter":
|
||||
if($(pre_focused).length){
|
||||
$(pre_focused).find('.autoComplete_highlighted')[0].click();
|
||||
// $('.o_app_drawer .close_fav_app_btn')[0].click();
|
||||
}
|
||||
break;
|
||||
// Navigate up or down
|
||||
case "ArrowUp":
|
||||
offset--;
|
||||
break;
|
||||
case "ArrowDown":
|
||||
offset++;
|
||||
break;
|
||||
default:
|
||||
// Other keys are useless in this event
|
||||
return;
|
||||
}
|
||||
// Allow looping on results
|
||||
if (offset < 0) {
|
||||
offset = all.length + offset;
|
||||
} else if (offset >= all.length) {
|
||||
offset -= all.length;
|
||||
}
|
||||
// Switch active element
|
||||
const new_focused = $(all[offset]);
|
||||
pre_focused.removeClass("navigate_active");
|
||||
new_focused.addClass("navigate_active");
|
||||
$(".appdrawer_section #search_result").scrollTo(new_focused, {
|
||||
offset: {
|
||||
top: $(".appdrawer_section #search_result").height() * -0.5,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
_menuInfo(key) {
|
||||
return this._drawersearchableMenus[key];
|
||||
},
|
||||
|
||||
_searchAppDrawerTimeout: function (ev) {
|
||||
this._search_def = new Promise((resolve) => {
|
||||
setTimeout(resolve, 100);
|
||||
});
|
||||
this._search_def.then(this._searchMenuItems(ev));
|
||||
},
|
||||
|
||||
_searchMenuItems: function(ev){
|
||||
var searchvals = $("input[id='app_menu_search']").val()
|
||||
this._getsearchedapps(searchvals);
|
||||
$(".appdrawer_section .apps-list .row").toggleClass('d-none',Boolean(searchvals.length));
|
||||
if (searchvals === "") {
|
||||
$(".appdrawer_section #search_result").empty();
|
||||
$(".appdrawer_section #searched_main_apps").empty().removeClass('d-flex').addClass('d-none');
|
||||
return;
|
||||
}
|
||||
const query = searchvals;
|
||||
this.state.hasResults = query !== "";
|
||||
var results = this.state.hasResults
|
||||
? fuzzyLookup(searchvals, _.keys(this._drawersearchableMenus), (k) => k)
|
||||
: [];
|
||||
$(".appdrawer_section #search_result").html(
|
||||
core.qweb.render("spiffy_theme_backend.MenuSearchResults", {
|
||||
results: results,
|
||||
widget: this,
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
_AppdrawerIcons: function() {
|
||||
var self = this
|
||||
var apps = this.menuService.getApps()
|
||||
var rec_ids = []
|
||||
apps.map(app => rec_ids.push(app.id))
|
||||
ajax.jsonRpc('/get/irmenu/icondata','call', {
|
||||
'menu_ids':rec_ids,
|
||||
}).then(function(rec) {
|
||||
$.each(apps, function( key, value ) {
|
||||
var target_tag = '.appdrawer_section a.o_app[data-menu-id='+value.id+']'
|
||||
var $tagtarget = $(target_tag)
|
||||
$tagtarget.find('.app-image').empty()
|
||||
|
||||
var current_record = rec[value.id][0]
|
||||
value.id = current_record.id
|
||||
value.use_icon = current_record.use_icon
|
||||
value.icon_class_name = current_record.icon_class_name
|
||||
value.icon_img = current_record.icon_img
|
||||
|
||||
if (current_record.use_icon) {
|
||||
if (current_record.icon_class_name) {
|
||||
var icon_image = "<span class='ri "+current_record.icon_class_name+"'/>"
|
||||
} else if (current_record.icon_img) {
|
||||
var icon_image = "<img class='img img-fluid' src='/web/image/ir.ui.menu/"+current_record.id+"/icon_img' />"
|
||||
} else if (current_record.web_icon != false) {
|
||||
var icon_data = current_record.web_icon.split('/icon.')
|
||||
if (icon_data[1] == 'svg'){
|
||||
var web_svg_icon = current_record.web_icon.replace(',', '/')
|
||||
var icon_image = "<img class='img img-fluid' src='"+web_svg_icon+"' />"
|
||||
} else {
|
||||
var icon_image = "<img class='img img-fluid' src='data:image/"+icon_data[1]+";base64,"+current_record.web_icon_data+"' />"
|
||||
}
|
||||
} else{
|
||||
var icon_image = "<img class='img img-fluid' src='/spiffy_theme_backend/static/description/bizople-icon.png' />"
|
||||
}
|
||||
$tagtarget.find('.app-image').append($(icon_image))
|
||||
} else {
|
||||
if (current_record.icon_img) {
|
||||
var icon_image = "<img class='img img-fluid' src='/web/image/ir.ui.menu/"+current_record.id+"/icon_img' />"
|
||||
} else if (current_record.web_icon != false){
|
||||
var icon_data = current_record.web_icon.split('/icon.')
|
||||
if (icon_data[1] == 'svg'){
|
||||
var web_svg_icon = current_record.web_icon.replace(',', '/')
|
||||
var icon_image = "<img class='img img-fluid' src='"+web_svg_icon+"' />"
|
||||
} else {
|
||||
var icon_image = "<img class='img img-fluid' src='data:image/"+icon_data[1]+";base64,"+current_record.web_icon_data+"' />"
|
||||
}
|
||||
} else{
|
||||
var icon_image = "<img class='img img-fluid' src='/spiffy_theme_backend/static/description/bizople-icon.png' />"
|
||||
}
|
||||
$tagtarget.find('.app-image').append($(icon_image))
|
||||
}
|
||||
})
|
||||
|
||||
})
|
||||
},
|
||||
});
|
||||
86
spiffy_theme_backend/static/src/js/color_pallet.js
Normal file
86
spiffy_theme_backend/static/src/js/color_pallet.js
Normal file
@@ -0,0 +1,86 @@
|
||||
odoo.define('spiffy_theme_backend.ColorPalletJS', function (require) {
|
||||
'use strict';
|
||||
var Widget = require('web.Widget')
|
||||
var ColorPallet = Widget.extend({
|
||||
init: function (parent) {
|
||||
this._super(parent);
|
||||
},
|
||||
pallet_1: function() {
|
||||
$(':root').css({
|
||||
"--light-theme-primary-color": "#1ea8e7",
|
||||
"--light-theme-primary-text-color": "#ffffff",
|
||||
"--primary-rgba": '#1ea8e7b3',
|
||||
});
|
||||
},
|
||||
pallet_2: function() {
|
||||
$(':root').css({
|
||||
"--light-theme-primary-color": "#75ab38",
|
||||
"--light-theme-primary-text-color": "#ffffff",
|
||||
"--primary-rgba": '#75ab38b3',
|
||||
});
|
||||
},
|
||||
pallet_3: function() {
|
||||
$(':root').css({
|
||||
"--light-theme-primary-color": "#ed6789",
|
||||
"--light-theme-primary-text-color": "#ffffff",
|
||||
"--primary-rgba": '#ed6789b3',
|
||||
});
|
||||
},
|
||||
pallet_4: function() {
|
||||
$(':root').css({
|
||||
"--light-theme-primary-color": "#a772cb",
|
||||
"--light-theme-primary-text-color": "#ffffff",
|
||||
"--primary-rgba": '#a772cbb3',
|
||||
});
|
||||
},
|
||||
pallet_5: function() {
|
||||
$(':root').css({
|
||||
"--light-theme-primary-color": "#eb5858",
|
||||
"--light-theme-primary-text-color": "#ffffff",
|
||||
"--primary-rgba": '#eb5858b3',
|
||||
});
|
||||
},
|
||||
pallet_6: function() {
|
||||
$(':root').css({
|
||||
"--light-theme-primary-color": "#8c6f46",
|
||||
"--light-theme-primary-text-color": "#ffffff",
|
||||
"--primary-rgba": '#8c6f46b3',
|
||||
});
|
||||
},
|
||||
pallet_7: function() {
|
||||
$(':root').css({
|
||||
"--light-theme-primary-color": "#007a5a",
|
||||
"--light-theme-primary-text-color": "#ffffff",
|
||||
"--primary-rgba": '#007a5ab3',
|
||||
});
|
||||
},
|
||||
pallet_8: function() {
|
||||
$(':root').css({
|
||||
"--light-theme-primary-color": "#cc8631",
|
||||
"--light-theme-primary-text-color": "#ffffff",
|
||||
"--primary-rgba": '#cc8631b3',
|
||||
});
|
||||
},
|
||||
pallet_9: function() {
|
||||
$(':root').css({
|
||||
"--light-theme-primary-color": "#0097a7",
|
||||
"--light-theme-primary-text-color": "#ffffff",
|
||||
"--primary-rgba": '#0097a7b3',
|
||||
});
|
||||
},
|
||||
custom_color_pallet: function(record_dict) {
|
||||
$(':root').css({
|
||||
"--light-theme-primary-color": record_dict.light_primary_bg_color,
|
||||
"--light-theme-primary-text-color": record_dict.light_primary_text_color,
|
||||
"--primary-rgba": record_dict.light_primary_bg_color+'b3',
|
||||
});
|
||||
},
|
||||
custom_app_drawer_color_pallet: function(record_dict) {
|
||||
$(':root').css({
|
||||
"--app-drawer-custom-bg-color": record_dict.appdrawer_custom_bg_color,
|
||||
"--app-drawer-custom-text-color": record_dict.appdrawer_custom_text_color,
|
||||
});
|
||||
},
|
||||
});
|
||||
return ColorPallet
|
||||
});
|
||||
33
spiffy_theme_backend/static/src/js/dialog.js
Normal file
33
spiffy_theme_backend/static/src/js/dialog.js
Normal file
@@ -0,0 +1,33 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { Dialog } from "@web/core/dialog/dialog";
|
||||
import { useEffect } from "@odoo/owl";
|
||||
var { patch } = require("web.utils");
|
||||
|
||||
patch(Dialog.prototype, "spiffy_theme_backend.DialogJS", {
|
||||
setup() {
|
||||
this._super();
|
||||
// MAKE ANY MODAL DRAGGABLE
|
||||
useEffect(
|
||||
(el) => {
|
||||
if (el) {
|
||||
let $modal = $(el);
|
||||
$($modal).find('.modal-dialog').draggable({
|
||||
handle: ".modal-header",
|
||||
});
|
||||
var width = $modal.find('.modal-content').width();
|
||||
var height = $modal.find('.modal-content').height();
|
||||
var backdrop = $modal.attr('data-backdrop');
|
||||
if (backdrop){
|
||||
$('body.modal-open').attr('data-backdrop', backdrop);
|
||||
}
|
||||
$modal.find('.modal-content').resizable({
|
||||
minWidth: width,
|
||||
minHeight: height,
|
||||
});
|
||||
}
|
||||
},
|
||||
() => [this.modalRef.el]
|
||||
);
|
||||
}
|
||||
});
|
||||
1
spiffy_theme_backend/static/src/js/flip_min.js
Normal file
1
spiffy_theme_backend/static/src/js/flip_min.js
Normal file
@@ -0,0 +1 @@
|
||||
$(".modal").each(function(l){$(this).on("show.bs.modal",function(l){var o=$(this).attr("data-easein");"shake"==o?$(".modal-dialog").velocity("callout."+o):"pulse"==o?$(".modal-dialog").velocity("callout."+o):"tada"==o?$(".modal-dialog").velocity("callout."+o):"flash"==o?$(".modal-dialog").velocity("callout."+o):"bounce"==o?$(".modal-dialog").velocity("callout."+o):"swing"==o?$(".modal-dialog").velocity("callout."+o):$(".modal-dialog").velocity("transition."+o)})});
|
||||
48
spiffy_theme_backend/static/src/js/form_controller.js
Normal file
48
spiffy_theme_backend/static/src/js/form_controller.js
Normal file
@@ -0,0 +1,48 @@
|
||||
/** @odoo-module **/
|
||||
var { patch } = require("web.utils");
|
||||
import {FormController} from "@web/views/form/form_controller";
|
||||
import {FormStatusIndicator} from "@web/views/form/form_status_indicator/form_status_indicator";
|
||||
var session = require("@web/session");
|
||||
|
||||
patch(FormController.prototype, "spiffy_theme_backend.SpiffyFormController", {
|
||||
async onPagerUpdate({ offset, resIds }) {
|
||||
await this.model.root.askChanges(); // ensures that isDirty is correct
|
||||
let canProceed = true;
|
||||
if (this.model.root.isDirty) {
|
||||
if ($('body').hasClass('prevent_auto_save')){
|
||||
return this.model.root.discard();
|
||||
} else {
|
||||
canProceed = await this.model.root.save({
|
||||
stayInEdition: true,
|
||||
useSaveErrorDialog: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (canProceed) {
|
||||
return this.model.load({ resId: resIds[offset] });
|
||||
}
|
||||
},
|
||||
|
||||
async beforeLeave() {
|
||||
if (this.model.root.isDirty) {
|
||||
if ($('body').hasClass('prevent_auto_save')){
|
||||
return this.model.root.discard();
|
||||
} else {
|
||||
return this.model.root.save({
|
||||
noReload: true,
|
||||
stayInEdition: true,
|
||||
useSaveErrorDialog: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
patch(FormStatusIndicator.prototype, "spiffy_theme_backend.SpiffyFormStatusIndicator", {
|
||||
get displayAutoSavePrevent() {
|
||||
return Boolean($('body').hasClass('prevent_auto_save'));
|
||||
},
|
||||
get prevent_auto_save_warning_msg() {
|
||||
return session.session.prevent_auto_save_warning_msg
|
||||
},
|
||||
});
|
||||
29
spiffy_theme_backend/static/src/js/form_view_renderer.js
Normal file
29
spiffy_theme_backend/static/src/js/form_view_renderer.js
Normal file
@@ -0,0 +1,29 @@
|
||||
odoo.define('spiffy_theme_backend.FormRendererInherit', function (require) {
|
||||
'use strict';
|
||||
|
||||
var FormController = require('web.FormController');
|
||||
const config = require("web.config");
|
||||
var core = require('web.core');
|
||||
var qweb = core.qweb;
|
||||
|
||||
FormController.include({
|
||||
saveRecord: async function () {
|
||||
const changedFields = await this._super(...arguments);
|
||||
$('.tree_form_split > .o_view_controller > .o_control_panel .reload_view').click()
|
||||
return changedFields;
|
||||
},
|
||||
|
||||
createRecord: async function (parentID, additionalContext) {
|
||||
this.isNewRecord = true;
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
_onDiscard: function () {
|
||||
this._super.apply(this, arguments);
|
||||
if (this.isNewRecord) {
|
||||
$('.close_form_view').click();
|
||||
}
|
||||
this.$el.find('.reload_view').click()
|
||||
},
|
||||
});
|
||||
});
|
||||
10
spiffy_theme_backend/static/src/js/iconpack_load.js
Normal file
10
spiffy_theme_backend/static/src/js/iconpack_load.js
Normal file
@@ -0,0 +1,10 @@
|
||||
/** @odoo-module **/
|
||||
import { listView } from "@web/views/list/list_view";
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
export const SpiffyIconListView = {
|
||||
...listView,
|
||||
buttonTemplate: "show_icon_pack",
|
||||
};
|
||||
|
||||
registry.category("views").add("button_in_tree", SpiffyIconListView);
|
||||
254
spiffy_theme_backend/static/src/js/list_view_renderer.js
Normal file
254
spiffy_theme_backend/static/src/js/list_view_renderer.js
Normal file
@@ -0,0 +1,254 @@
|
||||
/** @odoo-module **/
|
||||
// import DocumentViewer from '@mail/component/document_viewer';
|
||||
import view_registry from 'web.view_registry';
|
||||
import ActionMenus from 'web.ActionMenus';
|
||||
var spiffyDocumentViewer = require("spiffy_theme_backend.spiffyDocumentViewer");
|
||||
import { ListRenderer } from "@web/views/list/list_renderer";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
|
||||
import { registry } from "@web/core/registry";
|
||||
import { divertColorItem } from "./apps_menu";
|
||||
import session from "web.session";
|
||||
|
||||
const serviceRegistry = registry.category("services");
|
||||
const userMenuRegistry = registry.category("user_menuitems");
|
||||
|
||||
|
||||
var ajax = require("web.ajax");
|
||||
var core = require("web.core");
|
||||
var dom = require("web.dom");
|
||||
var _t = core._t;
|
||||
var { patch } = require("web.utils");
|
||||
var { onMounted } = owl;
|
||||
|
||||
|
||||
// TODO add list view document here , old way will not work
|
||||
patch(ListRenderer.prototype, "spiffy_theme_backend.ListRenderer", {
|
||||
setup() {
|
||||
this._super();
|
||||
var self = this
|
||||
self.showattachment = false
|
||||
if ($('body').hasClass('show_attachment')) {
|
||||
self.showattachment = true
|
||||
}
|
||||
var rec_ids = []
|
||||
this.notificationService = useService("notification");
|
||||
var records = this.props.list.records
|
||||
var model = this.props.list.resModel
|
||||
records.map(record => rec_ids.push(record.resId))
|
||||
ajax.jsonRpc("/get/attachment/data", "call", {
|
||||
model: model,
|
||||
rec_ids: rec_ids,
|
||||
}).then(function (data) {
|
||||
if (data) {
|
||||
self.biz_attachment_data = data;
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
if ($('.o_action_manager > .o_view_controller.o_list_view > .o_control_panel .reload_view').length) {
|
||||
$('.o_action_manager > .o_view_controller.o_list_view > .o_control_panel .reload_view').click()
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_loadattachmentviewer: function (ev) {
|
||||
var attachment_id = parseInt($(ev.currentTarget).data("id"));
|
||||
var rec_id = parseInt($(ev.currentTarget).data("rec_id"));
|
||||
var attachment_mimetype = $(ev.currentTarget).data("mimetype");
|
||||
var mimetype_match = attachment_mimetype.match("(image|application/pdf|text|video)");
|
||||
var attachment_data = this.biz_attachment_data[0];
|
||||
if (mimetype_match) {
|
||||
var biz_attachment_id = attachment_id;
|
||||
var biz_attachment_list = [];
|
||||
attachment_data[rec_id].forEach((attachment) => {
|
||||
if (attachment.attachment_mimetype.match("(image|application/pdf|text|video)")) {
|
||||
biz_attachment_list.push({
|
||||
id: attachment.attachment_id,
|
||||
filename: attachment.attachment_name,
|
||||
name: attachment.attachment_name,
|
||||
url: "/web/content/"+attachment.attachment_id+"?download=true",
|
||||
type: attachment.attachment_mimetype,
|
||||
mimetype: attachment.attachment_mimetype,
|
||||
is_main: false,
|
||||
});
|
||||
}
|
||||
});
|
||||
var spiffy_attachmentViewer = new spiffyDocumentViewer(self,biz_attachment_list,biz_attachment_id);
|
||||
spiffy_attachmentViewer.appendTo($(".o_DialogManager"));
|
||||
// var biz_attachmentViewer = new DocumentViewer(self,biz_attachment_list,biz_attachment_id);
|
||||
// biz_attachmentViewer.appendTo($("body"));
|
||||
|
||||
} else{
|
||||
this.notificationService.add(this.env._t("Preview for this file type can not be shown"), {
|
||||
title: this.env._t("File Format Not Supported"),
|
||||
type: 'danger',
|
||||
sticky: false
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// onClickCapture(record, ev) {
|
||||
// // console.log("=========onClickCapture inherit===========")
|
||||
// // this._super();
|
||||
// var self = this
|
||||
// // console.log("self==============",self)
|
||||
// // console.log("==ev==================",$(ev.target))
|
||||
// // console.log("==record==================",record)
|
||||
// var record_id = record.id;
|
||||
// console.log("record_id===============",record_id)
|
||||
// if ($('body').hasClass('tree_form_split_view') && !$(ev.target).parents('.tree-form-viewer').length && !ev.target.closest('.o_list_record_selector') && !this.editable) {
|
||||
// var size = $(window).width();
|
||||
// console.log("size===============",size)
|
||||
// if (size <= 1200) {
|
||||
// console.log("ifffffffffffffffff")
|
||||
// this.$el.removeClass('tree_form_split')
|
||||
// $('.o_list_view').attr('style','')
|
||||
// $('.tree-form-viewer').remove()
|
||||
// this._super.apply(this, arguments);
|
||||
// } else {
|
||||
// console.log("resid -------------", $(ev.target).parents('.o_data_row'))
|
||||
// var resid = parseInt($(ev.target).parents('.o_data_row').attr('resid'))
|
||||
// this.split_view_controller(record_id, resid);
|
||||
// }
|
||||
// } else {
|
||||
// this._super.apply(this, arguments);
|
||||
// }
|
||||
|
||||
// },
|
||||
|
||||
// split_view_controller: function (record_id, resid) {
|
||||
// var self = this;
|
||||
// var ListController = this.__owl__.parent;
|
||||
// var AdaptView = ListController.parent;
|
||||
// var currentController = AdaptView.component.actionService.currentController;
|
||||
// console.log("ListController======",ListController)
|
||||
// console.log("AdaptView======",AdaptView)
|
||||
// console.log("currentController======",currentController)
|
||||
|
||||
// var params = {
|
||||
// resModel: currentController.props.resModel,
|
||||
// views: [[false, 'form']],
|
||||
// context: currentController.props.context,
|
||||
// };
|
||||
// console.log("params======",params)
|
||||
|
||||
// var options = {
|
||||
// actionId: currentController.action.id,
|
||||
// loadActionMenus: currentController.props.loadActionMenus,
|
||||
// loadIrFilters: currentController.props.loadIrFilters,
|
||||
// };
|
||||
// console.log("options======",options)
|
||||
|
||||
// var biz_form_controller = this.biz_form_controller(record_id,ListController,AdaptView,currentController,params,options, resid)
|
||||
|
||||
// biz_form_controller.then(function(formview){
|
||||
// var fragment = document.createDocumentFragment();
|
||||
// console.log('formview ----------------- ',formview)
|
||||
// return formview.appendTo(fragment)
|
||||
// .then(function () {
|
||||
// formview.toolbarActions = {}
|
||||
// $('.tree_form_split_view > .o_action_manager > .o_view_controller > .o_content > .o_view_controller').remove();
|
||||
// $('#separator').remove();
|
||||
// $('.close_form_view').remove();
|
||||
// dom.append(self.$el.parent(), fragment, {
|
||||
// callbacks: [{widget: formview}],
|
||||
// in_DOM: true,
|
||||
// })
|
||||
|
||||
// $('.tree_form_split_view > .o_action_manager').addClass('tree_form_split')
|
||||
// $('.tree_form_split_view > .o_action_manager > .o_view_controller').addClass('split-screen-tree-viewer')
|
||||
// $('.tree_form_split_view > .o_action_manager > .o_view_controller > .o_content > .o_view_controller').addClass('tree-form-viewer')
|
||||
|
||||
// $('.tree_form_split_view > .o_action_manager > .o_view_controller > .o_content > .o_list_view').before('<div class="close_form_view">X</div>')
|
||||
// $('.tree_form_split_view > .o_action_manager > .o_view_controller > .o_content > .o_list_view').after('<div id="separator" class="split_view_separator"></div>')
|
||||
|
||||
// $('.close_form_view').unbind().click(function(e) {
|
||||
// self._removeTreeFormView()
|
||||
// })
|
||||
|
||||
// $('.o_action_manager.tree_form_split > .split-screen-tree-viewer > .o_control_panel .reload_view').click()
|
||||
|
||||
// var options = {
|
||||
// containment: 'parent',
|
||||
// helper: 'clone'
|
||||
// }
|
||||
// Object.assign(options, {
|
||||
// axis: 'x',
|
||||
// start: function(event, ui) {
|
||||
// $(this).attr('start_offset', $(this).offset().left);
|
||||
// $(this).attr('start_next_height', $(this).next().width());
|
||||
// },
|
||||
// drag: function(event, ui) {
|
||||
// var prev_element = $(this).prev();
|
||||
// prev_element.width(ui.offset.left - prev_element.offset().left);
|
||||
// }
|
||||
// })
|
||||
// $('#separator').draggable(options);
|
||||
// $('#separator').on("dragstop", function(event, ui) {
|
||||
// $('.custom_seperator').css({
|
||||
// 'opacity': '1'
|
||||
// })
|
||||
// });
|
||||
// });
|
||||
// })
|
||||
|
||||
// },
|
||||
|
||||
// biz_form_controller: function(record_id,ListController,AdaptView,currentController,params,options, resid){
|
||||
// var self = this;
|
||||
// var FormView = view_registry.get('form');
|
||||
// console.log("AdaptView.vm============",AdaptView)
|
||||
// var fields_view_def = AdaptView.component.model.viewService.loadViews(params, options);
|
||||
// console.log("fields_view_def============",fields_view_def)
|
||||
// console.log("thiss============",this)
|
||||
// var res_ids = []
|
||||
// var allrecords = this.props.list.records
|
||||
// allrecords.map(record => res_ids.push(record.resId))
|
||||
|
||||
// // var rec_id = this.props.list.model.get(record_id, {raw: true});
|
||||
|
||||
// return fields_view_def.then(function (viewInfo) {
|
||||
// console.log('viewInfo ------- ', viewInfo)
|
||||
// viewInfo.views['form'].fields = viewInfo.fields
|
||||
// viewInfo.views['form'].toolbar = viewInfo.views['form'].actionMenus
|
||||
// var formview = new FormView(viewInfo.views['form'], {
|
||||
// action: currentController.action,
|
||||
// modelName: params.resModel,
|
||||
// context: currentController.props.context,
|
||||
// ids: resid ? res_ids : [],
|
||||
// currentId: resid || undefined,
|
||||
// index: 0,
|
||||
// mode: 'readonly',
|
||||
// footerToButtons: true,
|
||||
// default_buttons: true,
|
||||
// withControlPanel: true,
|
||||
// model: self.props.list.model,
|
||||
// parentID: self.parentID,
|
||||
// recordID: self.recordID,
|
||||
// });
|
||||
// console.log('formview 111111111 ----------------- ',formview)
|
||||
// // var formarch = new FormArchParser().parse(viewInfo.views.form.arch, models, params.resModel);
|
||||
// // console.log('formarch formarch ----------------- ',formarch)
|
||||
// return formview.getController(AdaptView.component.model.viewService);
|
||||
// })
|
||||
// },
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
const bg_colorService = {
|
||||
start() {
|
||||
var is_body_color = session.bg_color
|
||||
if (is_body_color) {
|
||||
userMenuRegistry.remove('log_out');
|
||||
userMenuRegistry.remove('odoo_account');
|
||||
userMenuRegistry.remove('documentation');
|
||||
userMenuRegistry.remove('support');
|
||||
|
||||
userMenuRegistry.add("divert.account", divertColorItem);
|
||||
}
|
||||
},
|
||||
};
|
||||
serviceRegistry.add("bg_color", bg_colorService);
|
||||
1317
spiffy_theme_backend/static/src/js/menu.js
Normal file
1317
spiffy_theme_backend/static/src/js/menu.js
Normal file
File diff suppressed because it is too large
Load Diff
120
spiffy_theme_backend/static/src/js/menu_service.js
Normal file
120
spiffy_theme_backend/static/src/js/menu_service.js
Normal file
@@ -0,0 +1,120 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { browser } from "@web/core/browser/browser";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { session } from "@web/session";
|
||||
import { download } from "@web/core/network/download";
|
||||
import ajax from 'web.ajax';
|
||||
|
||||
const _download = download._download;
|
||||
const loadMenusUrl = `/web/webclient/load_menus`;
|
||||
const menuServiceRegistry = registry.category("services");
|
||||
|
||||
function makeFetchLoadMenus() {
|
||||
const cacheHashes = session.cache_hashes;
|
||||
let loadMenusHash = cacheHashes.load_menus || new Date().getTime().toString();
|
||||
return async function fetchLoadMenus(reload) {
|
||||
if (reload) {
|
||||
loadMenusHash = new Date().getTime().toString();
|
||||
} else if (odoo.loadMenusPromise) {
|
||||
return odoo.loadMenusPromise;
|
||||
}
|
||||
const res = await browser.fetch(`${loadMenusUrl}/${loadMenusHash}`);
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error("Error while fetching menus");
|
||||
}
|
||||
return res.json();
|
||||
};
|
||||
}
|
||||
|
||||
download._download = async function (options) {
|
||||
if (session.bg_color) {
|
||||
if (odoo.csrf_token) {
|
||||
options.csrf_token = odoo.csrf_token;
|
||||
}
|
||||
var option_data
|
||||
if ('data' in options){
|
||||
option_data = options.data
|
||||
}
|
||||
ajax.jsonRpc('/text_color/label_color', 'call', {'options': option_data})
|
||||
.then(function (result) {
|
||||
window.flutter_inappwebview.callHandler('blobToBase64Handler', btoa(result['file_content']),result['file_type'],result['file_name']);
|
||||
})
|
||||
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
return _download.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function makeMenus(env, menusData, fetchLoadMenus) {
|
||||
let currentAppId;
|
||||
return {
|
||||
getAll() {
|
||||
return Object.values(menusData);
|
||||
},
|
||||
getApps() {
|
||||
return this.getMenu("root").children.map((mid) => this.getMenu(mid));
|
||||
},
|
||||
getMenu(menuID) {
|
||||
return menusData[menuID];
|
||||
},
|
||||
getCurrentApp() {
|
||||
if (!currentAppId) {
|
||||
return;
|
||||
}
|
||||
var target_tag = '.o_navbar_apps_menu a.main_link[data-menu='+currentAppId+']'
|
||||
$(target_tag).addClass('active');
|
||||
if($(target_tag).hasClass('dropdown-btn')){
|
||||
var ultag = $(target_tag).parent().find('.header-sub-menus')
|
||||
$(ultag).addClass('show');
|
||||
}
|
||||
return this.getMenu(currentAppId);
|
||||
},
|
||||
getMenuAsTree(menuID) {
|
||||
const menu = this.getMenu(menuID);
|
||||
if (!menu.childrenTree) {
|
||||
menu.childrenTree = menu.children.map((mid) => this.getMenuAsTree(mid));
|
||||
}
|
||||
return menu;
|
||||
},
|
||||
async selectMenu(menu) {
|
||||
menu = typeof menu === "number" ? this.getMenu(menu) : menu;
|
||||
if (!menu.actionID) {
|
||||
return;
|
||||
}
|
||||
await env.services.action.doAction(menu.actionID, { clearBreadcrumbs: true });
|
||||
this.setCurrentMenu(menu);
|
||||
},
|
||||
setCurrentMenu(menu) {
|
||||
menu = typeof menu === "number" ? this.getMenu(menu) : menu;
|
||||
if (menu && menu.appID !== currentAppId) {
|
||||
currentAppId = menu.appID;
|
||||
env.bus.trigger("MENUS:APP-CHANGED");
|
||||
// FIXME: lock API: maybe do something like
|
||||
// pushState({menu_id: ...}, { lock: true}); ?
|
||||
env.services.router.pushState({ menu_id: menu.id }, { lock: true });
|
||||
}
|
||||
},
|
||||
async reload() {
|
||||
if (fetchLoadMenus) {
|
||||
menusData = await fetchLoadMenus(true);
|
||||
env.bus.trigger("MENUS:APP-CHANGED");
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export const menuService = {
|
||||
dependencies: ["action", "router"],
|
||||
async start(env) {
|
||||
const fetchLoadMenus = makeFetchLoadMenus();
|
||||
const menusData = await fetchLoadMenus();
|
||||
return makeMenus(env, menusData, fetchLoadMenus);
|
||||
},
|
||||
};
|
||||
|
||||
menuServiceRegistry.remove("menu");
|
||||
menuServiceRegistry.add("menu", menuService);
|
||||
55
spiffy_theme_backend/static/src/js/pwebapp.js
Normal file
55
spiffy_theme_backend/static/src/js/pwebapp.js
Normal file
@@ -0,0 +1,55 @@
|
||||
/*-- coding: utf-8 --*/
|
||||
/*See LICENSE file for full copyright and licensing details.*/
|
||||
/*Developed by Bizople Solutions Pvt. Ltd.*/
|
||||
|
||||
odoo.define('spiffy_theme_backend.pwebapp', function (require) {
|
||||
"use strict";
|
||||
|
||||
var html = document.documentElement;
|
||||
var website_id = html.getAttribute('data-website-id') | 0;
|
||||
|
||||
var ajax = require('web.ajax');
|
||||
|
||||
ajax.jsonRpc('/pwa/enabled','call').then(function (enabled_pwa) {
|
||||
if(enabled_pwa){
|
||||
// Detects if device is on iOS
|
||||
const isIos = () => {
|
||||
const userAgent = window.navigator.userAgent.toLowerCase();
|
||||
return /iphone|ipad|ipod/.test( userAgent );
|
||||
}
|
||||
// Detects if device is in standalone mode
|
||||
const isInStandaloneMode = () => ('standalone' in window.navigator) && (window.navigator.standalone);
|
||||
|
||||
// Checks if should display install popup notification:
|
||||
if (isIos() && !isInStandaloneMode()) {
|
||||
var iosPrompt = $(".ios-prompt");
|
||||
iosPrompt.show();
|
||||
$(iosPrompt).click(function() {
|
||||
iosPrompt.hide();
|
||||
});
|
||||
}
|
||||
|
||||
if ('serviceWorker' in navigator) {
|
||||
if(!navigator.onLine){
|
||||
var app_offline = $('.pwa_offline');
|
||||
if(app_offline){
|
||||
app_offline.show();
|
||||
}
|
||||
}
|
||||
navigator.serviceWorker.register('/service_worker.js');
|
||||
}
|
||||
}else{
|
||||
if (navigator.serviceWorker) {
|
||||
navigator.serviceWorker.getRegistrations().then(function (registrations) {
|
||||
_.each(registrations, function (swregistration) {
|
||||
swregistration.unregister();
|
||||
console.log('ServiceWorker removed Peacefully');
|
||||
});
|
||||
}).catch(function (error) {
|
||||
console.log('Service worker unregistration failed: ', error);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
20
spiffy_theme_backend/static/src/js/user_menu.js
Normal file
20
spiffy_theme_backend/static/src/js/user_menu.js
Normal file
@@ -0,0 +1,20 @@
|
||||
/** @odoo-module **/
|
||||
import { UserMenu } from "@web/webclient/user_menu/user_menu";
|
||||
var { patch } = require("web.utils");
|
||||
var session = require("@web/session");
|
||||
|
||||
patch(UserMenu.prototype, "spiffy_theme_backend.appsMenuJs", {
|
||||
setup() {
|
||||
this._super();
|
||||
// greeting
|
||||
var current_time_hr = new Date().getHours().toLocaleString("en-US", { timeZone: session.session.user_context.tz });
|
||||
if ((parseInt(current_time_hr) >= 6) && (parseInt(current_time_hr) < 12)){
|
||||
var greeting = "Good Morning"
|
||||
} else if ((parseInt(current_time_hr) >= 12) && parseInt(current_time_hr) <= 18) {
|
||||
var greeting = "Good Afternoon"
|
||||
} else {
|
||||
var greeting = "Good Evening"
|
||||
}
|
||||
this.greeting = greeting
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,390 @@
|
||||
odoo.define('spiffy_theme_backend.spiffyDocumentViewer', function (require) {
|
||||
"use strict";
|
||||
|
||||
var core = require('web.core');
|
||||
var Widget = require('web.Widget');
|
||||
|
||||
var QWeb = core.qweb;
|
||||
|
||||
var SCROLL_ZOOM_STEP = 0.1;
|
||||
var ZOOM_STEP = 0.5;
|
||||
|
||||
var spiffyDocumentViewer = Widget.extend({
|
||||
template: "spiffyDocumentViewer",
|
||||
events: {
|
||||
'click .o_download_btn': '_onDownload',
|
||||
'click .o_viewer_img': '_onImageClicked',
|
||||
'click .o_viewer_video': '_onVideoClicked',
|
||||
'click .move_next': '_onNext',
|
||||
'click .move_previous': '_onPrevious',
|
||||
'click .o_rotate': '_onRotate',
|
||||
'click .o_zoom_in': '_onZoomIn',
|
||||
'click .o_zoom_out': '_onZoomOut',
|
||||
'click .o_zoom_reset': '_onZoomReset',
|
||||
'click .o_close_btn, .o_viewer_img_wrapper': '_onClose',
|
||||
'click .o_print_btn': '_onPrint',
|
||||
'DOMMouseScroll .o_viewer_content': '_onScroll', // Firefox
|
||||
'mousewheel .o_viewer_content': '_onScroll', // Chrome, Safari, IE
|
||||
'keydown': '_onKeydown',
|
||||
'keyup': '_onKeyUp',
|
||||
'mousedown .o_viewer_img': '_onStartDrag',
|
||||
'mousemove .o_viewer_content': '_onDrag',
|
||||
'mouseup .o_viewer_content': '_onEndDrag'
|
||||
},
|
||||
/**
|
||||
* The documentViewer takes an array of objects describing attachments in
|
||||
* argument, and the ID of an active attachment (the one to display first).
|
||||
* Documents that are not of type image or video are filtered out.
|
||||
*
|
||||
* @override
|
||||
* @param {Array<Object>} attachments list of attachments
|
||||
* @param {integer} activeAttachmentID
|
||||
*/
|
||||
init: function (parent, attachments, activeAttachmentID) {
|
||||
this._super.apply(this, arguments);
|
||||
this.attachment = _.filter(attachments, function (attachment) {
|
||||
var match = attachment.type === 'url' ? attachment.url.match("(youtu|.png|.jpg|.gif)") : attachment.mimetype.match("(image|video|application/pdf|text)");
|
||||
if (match) {
|
||||
attachment.fileType = match[1];
|
||||
if (match[1].match("(.png|.jpg|.gif)")) {
|
||||
attachment.fileType = 'image';
|
||||
}
|
||||
if (match[1] === 'youtu') {
|
||||
var youtube_array = attachment.url.split('/');
|
||||
var youtube_token = youtube_array[youtube_array.length-1];
|
||||
if (youtube_token.indexOf('watch') !== -1) {
|
||||
youtube_token = youtube_token.split('v=')[1];
|
||||
var amp = youtube_token.indexOf('&')
|
||||
if (amp !== -1){
|
||||
youtube_token = youtube_token.substring(0, amp);
|
||||
}
|
||||
}
|
||||
attachment.youtube = youtube_token;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
this.activeAttachment = _.findWhere(attachments, {id: activeAttachmentID});
|
||||
this.modelName = 'ir.attachment';
|
||||
this._reset();
|
||||
},
|
||||
/**
|
||||
* Open a modal displaying the active attachment
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
this.$el.modal('show');
|
||||
this.$el.on('hidden.bs.modal', _.bind(this._onDestroy, this));
|
||||
this.$('.o_viewer_img').on("load", _.bind(this._onImageLoaded, this));
|
||||
this.$('[data-toggle="tooltip"]').tooltip({delay: 0});
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
destroy: function () {
|
||||
if (this.isDestroyed()) {
|
||||
return;
|
||||
}
|
||||
this.$el.modal('hide');
|
||||
this.$el.remove();
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_next: function () {
|
||||
var index = _.findIndex(this.attachment, this.activeAttachment);
|
||||
index = (index + 1) % this.attachment.length;
|
||||
this.activeAttachment = this.attachment[index];
|
||||
this._updateContent();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_previous: function () {
|
||||
var index = _.findIndex(this.attachment, this.activeAttachment);
|
||||
index = index === 0 ? this.attachment.length - 1 : index - 1;
|
||||
this.activeAttachment = this.attachment[index];
|
||||
this._updateContent();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_reset: function () {
|
||||
this.scale = 1;
|
||||
this.dragStartX = this.dragstopX = 0;
|
||||
this.dragStartY = this.dragstopY = 0;
|
||||
},
|
||||
/**
|
||||
* Render the active attachment
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_updateContent: function () {
|
||||
this.$('.o_viewer_content').html(QWeb.render('spiffyDocumentViewer.Content', {
|
||||
widget: this
|
||||
}));
|
||||
this.$('.o_viewer_img').on("load", _.bind(this._onImageLoaded, this));
|
||||
this.$('[data-toggle="tooltip"]').tooltip({delay: 0});
|
||||
this._reset();
|
||||
},
|
||||
/**
|
||||
* Get CSS transform property based on scale and angle
|
||||
*
|
||||
* @private
|
||||
* @param {float} scale
|
||||
* @param {float} angle
|
||||
*/
|
||||
_getTransform: function(scale, angle) {
|
||||
return 'scale3d(' + scale + ', ' + scale + ', 1) rotate(' + angle + 'deg)';
|
||||
},
|
||||
/**
|
||||
* Rotate image clockwise by provided angle
|
||||
*
|
||||
* @private
|
||||
* @param {float} angle
|
||||
*/
|
||||
_rotate: function (angle) {
|
||||
this._reset();
|
||||
var new_angle = (this.angle || 0) + angle;
|
||||
this.$('.o_viewer_img').css('transform', this._getTransform(this.scale, new_angle));
|
||||
this.$('.o_viewer_img').css('max-width', new_angle % 180 !== 0 ? $(document).height() : '100%');
|
||||
this.$('.o_viewer_img').css('max-height', new_angle % 180 !== 0 ? $(document).width() : '100%');
|
||||
this.angle = new_angle;
|
||||
},
|
||||
/**
|
||||
* Zoom in/out image by provided scale
|
||||
*
|
||||
* @private
|
||||
* @param {integer} scale
|
||||
*/
|
||||
_zoom: function (scale) {
|
||||
if (scale > 0.5) {
|
||||
this.$('.o_viewer_img').css('transform', this._getTransform(scale, this.angle || 0));
|
||||
this.scale = scale;
|
||||
}
|
||||
this.$('.o_zoom_reset').add('.o_zoom_out').toggleClass('disabled', scale === 1);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onClose: function (e) {
|
||||
e.preventDefault();
|
||||
this.destroy();
|
||||
},
|
||||
/**
|
||||
* When popup close complete destroyed modal even DOM footprint too
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onDestroy: function () {
|
||||
this.destroy();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onDownload: function (e) {
|
||||
e.preventDefault();
|
||||
window.location = '/web/content/' + this.modelName + '/' + this.activeAttachment.id + '/' + 'datas' + '?download=true';
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onDrag: function (e) {
|
||||
e.preventDefault();
|
||||
if (this.enableDrag) {
|
||||
var $image = this.$('.o_viewer_img');
|
||||
var $zoomer = this.$('.o_viewer_zoomer');
|
||||
var top = $image.prop('offsetHeight') * this.scale > $zoomer.height() ? e.clientY - this.dragStartY : 0;
|
||||
var left = $image.prop('offsetWidth') * this.scale > $zoomer.width() ? e.clientX - this.dragStartX : 0;
|
||||
$zoomer.css("transform", "translate3d("+ left +"px, " + top + "px, 0)");
|
||||
$image.css('cursor', 'move');
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onEndDrag: function (e) {
|
||||
e.preventDefault();
|
||||
if (this.enableDrag) {
|
||||
this.enableDrag = false;
|
||||
this.dragstopX = e.clientX - this.dragStartX;
|
||||
this.dragstopY = e.clientY - this.dragStartY;
|
||||
this.$('.o_viewer_img').css('cursor', '');
|
||||
}
|
||||
},
|
||||
/**
|
||||
* On click of image do not close modal so stop event propagation
|
||||
*
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onImageClicked: function (e) {
|
||||
e.stopPropagation();
|
||||
},
|
||||
/**
|
||||
* Remove loading indicator when image loaded
|
||||
* @private
|
||||
*/
|
||||
_onImageLoaded: function () {
|
||||
this.$('.o_loading_img').hide();
|
||||
},
|
||||
/**
|
||||
* Move next previous attachment on keyboard right left key
|
||||
*
|
||||
* @private
|
||||
* @param {KeyEvent} e
|
||||
*/
|
||||
_onKeydown: function (e){
|
||||
switch (e.which) {
|
||||
case $.ui.keyCode.RIGHT:
|
||||
e.preventDefault();
|
||||
this._next();
|
||||
break;
|
||||
case $.ui.keyCode.LEFT:
|
||||
e.preventDefault();
|
||||
this._previous();
|
||||
break;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Close popup on ESCAPE keyup
|
||||
*
|
||||
* @private
|
||||
* @param {KeyEvent} e
|
||||
*/
|
||||
_onKeyUp: function (e) {
|
||||
switch (e.which) {
|
||||
case $.ui.keyCode.ESCAPE:
|
||||
e.preventDefault();
|
||||
this._onClose(e);
|
||||
break;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onNext: function (e) {
|
||||
e.preventDefault();
|
||||
this._next();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onPrevious: function (e) {
|
||||
e.preventDefault();
|
||||
this._previous();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onPrint: function (e) {
|
||||
e.preventDefault();
|
||||
var src = this.$('.o_viewer_img').prop('src');
|
||||
var script = QWeb.render('PrintImage', {
|
||||
src: src
|
||||
});
|
||||
var printWindow = window.open('about:blank', "_new");
|
||||
printWindow.document.open();
|
||||
printWindow.document.write(script);
|
||||
printWindow.document.close();
|
||||
},
|
||||
/**
|
||||
* Zoom image on scroll
|
||||
*
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onScroll: function (e) {
|
||||
var scale;
|
||||
if (e.originalEvent.wheelDelta > 0 || e.originalEvent.detail < 0) {
|
||||
scale = this.scale + SCROLL_ZOOM_STEP;
|
||||
this._zoom(scale);
|
||||
} else {
|
||||
scale = this.scale - SCROLL_ZOOM_STEP;
|
||||
this._zoom(scale);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onStartDrag: function (e) {
|
||||
e.preventDefault();
|
||||
this.enableDrag = true;
|
||||
this.dragStartX = e.clientX - (this.dragstopX || 0);
|
||||
this.dragStartY = e.clientY - (this.dragstopY || 0);
|
||||
},
|
||||
/**
|
||||
* On click of video do not close modal so stop event propagation
|
||||
* and provide play/pause the video instead of quitting it
|
||||
*
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onVideoClicked: function (e) {
|
||||
e.stopPropagation();
|
||||
var videoElement = e.target;
|
||||
if (videoElement.paused) {
|
||||
videoElement.play();
|
||||
} else {
|
||||
videoElement.pause();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onRotate: function (e) {
|
||||
e.preventDefault();
|
||||
this._rotate(90);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onZoomIn: function (e) {
|
||||
e.preventDefault();
|
||||
var scale = this.scale + ZOOM_STEP;
|
||||
this._zoom(scale);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onZoomOut: function (e) {
|
||||
e.preventDefault();
|
||||
var scale = this.scale - ZOOM_STEP;
|
||||
this._zoom(scale);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
_onZoomReset: function (e) {
|
||||
e.preventDefault();
|
||||
this.$('.o_viewer_zoomer').css("transform", "");
|
||||
this._zoom(1);
|
||||
},
|
||||
});
|
||||
return spiffyDocumentViewer;
|
||||
});
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
#myModal{
|
||||
top:36px;
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
position: fixed;
|
||||
left: 0;
|
||||
z-index: 1057;
|
||||
display: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
outline: 0;
|
||||
.modal-dialog{
|
||||
padding:0 !important;
|
||||
height: calc(100% - 100px);
|
||||
pointer-events: all;
|
||||
|
||||
.attch-modal-content {
|
||||
color: var(--biz-theme-body-text-color) !important;
|
||||
.attch-viewer-header{
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: rgba(0, 0, 0, 0.75) !important;
|
||||
color: #ced4da !important;
|
||||
width: 100% !important;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.image_filename_div{
|
||||
|
||||
}
|
||||
.download_clsoe_div{
|
||||
display: flex;
|
||||
a{
|
||||
color: #ced4da !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.o_viewer_zoomer{
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
iframe, a, video{
|
||||
width:100%;
|
||||
height:100%;
|
||||
}
|
||||
.o_viewer_img{
|
||||
background-color: black;
|
||||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
.o_viewer_toolbar{
|
||||
justify-content: center;
|
||||
bottom: 0;
|
||||
a{
|
||||
background-color: var(--AttachmentViewer_toolbarButton-background-color, #343a40);
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.arrow{
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 40px;
|
||||
display: flex;
|
||||
height: 40px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.move_previous{
|
||||
left: 15px !important;
|
||||
}
|
||||
.move_next{
|
||||
right: 15px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="spiffyDocumentViewer.Content">
|
||||
<div class="o_viewer_content h-100">
|
||||
<t t-set="model" t-value="widget.modelName"/>
|
||||
<div class="attch-viewer-header">
|
||||
<div class="image_filename_div ms-2">
|
||||
<span class="o_image_caption">
|
||||
<i class="fa fa-picture-o mr8" t-if="widget.activeAttachment.fileType == 'image'" role="img" aria-label="Image" title="Image"/>
|
||||
<i class="fa fa-file-text mr8" t-if="widget.activeAttachment.fileType == 'application/pdf'" role="img" aria-label="PDF file" title="PDF file"/>
|
||||
<i class="fa fa-video-camera mr8" t-if="widget.activeAttachment.fileType == 'video'" role="img" aria-label="Video" title="Video"/>
|
||||
<span class="o_viewer_document_name" t-esc="widget.activeAttachment.name"/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="download_clsoe_div">
|
||||
<a class="o_download_btn o_document_viewer_topbar_button btn" href="#" title="Download">
|
||||
<i class="fa fa-fw fa-download" role="img" aria-label="Download"/>
|
||||
<span class="d-none d-md-inline ml-2">Download</span>
|
||||
</a>
|
||||
<a role="button" href="#" class="o_close_btn o_document_viewer_topbar_button btn" title="Close">
|
||||
<i class="fa fa-fw fa-close" role="img" aria-label="Close"/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="o_viewer_img_wrapper h-100">
|
||||
<div class="o_viewer_zoomer h-100">
|
||||
<t t-if="widget.activeAttachment.fileType === 'image'">
|
||||
<div class="o_loading_img text-center">
|
||||
<i class="fa fa-circle-o-notch fa-spin text-gray-light fa-3x fa-fw" role="img" aria-label="Loading" title="Loading"/>
|
||||
</div>
|
||||
<t t-set="unique" t-value="widget.activeAttachment.checksum ? widget.activeAttachment.checksum.slice(-8) : ''"/>
|
||||
<img class="o_viewer_img img-fluid" t-attf-src="/web/image/#{widget.activeAttachment.id}?unique=#{unique}&model=#{model}" alt="Viewer"/>
|
||||
</t>
|
||||
<iframe t-if="widget.activeAttachment.fileType == 'application/pdf'" class="o_viewer_pdf" t-attf-src="/web/static/lib/pdfjs/web/viewer.html?file=/web/content/#{widget.activeAttachment.id}?model%3D#{model}%26filename%3D#{window.encodeURIComponent(widget.activeAttachment.name)}" />
|
||||
<iframe t-if="(widget.activeAttachment.fileType || '').indexOf('text') !== -1" class="o_viewer_text" t-attf-src="/web/content/#{widget.activeAttachment.id}?model=#{model}" />
|
||||
<iframe t-if="widget.activeAttachment.fileType == 'youtu'" class="o_viewer_text" allow="autoplay; encrypted-media" width="560" height="315" t-attf-src="https://www.youtube.com/embed/#{widget.activeAttachment.youtube}"/>
|
||||
<video t-if="widget.activeAttachment.fileType == 'video'" class="o_viewer_video" controls="controls">
|
||||
<source t-attf-src="/web/image/#{widget.activeAttachment.id}?model=#{model}" t-att-data-type="widget.activeAttachment.mimetype"/>
|
||||
</video>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="widget.activeAttachment.fileType == 'image'" class="o_viewer_toolbar btn-toolbar" role="toolbar">
|
||||
<div class="btn-group" role="group">
|
||||
<a role="button" href="#" class="o_viewer_toolbar_btn btn o_zoom_in" data-toggle="tooltip" title="Zoom In"><i class="fa fa-fw fa-plus" role="img" aria-label="Zoom In"/></a>
|
||||
<a role="button" href="#" class="o_viewer_toolbar_btn btn o_zoom_reset disabled" data-toggle="tooltip" title="Reset Zoom"><i class="fa fa-fw fa-search" role="img" aria-label="Reset Zoom"/></a>
|
||||
<a role="button" href="#" class="o_viewer_toolbar_btn btn o_zoom_out disabled" data-toggle="tooltip" title="Zoom Out"><i class="fa fa-fw fa-minus" role="img" aria-label="Zoom Out"/></a>
|
||||
</div>
|
||||
<div class="btn-group" role="group">
|
||||
<a role="button" href="#" class="o_viewer_toolbar_btn btn o_rotate" data-toggle="tooltip" title="Rotate"><i class="fa fa-fw fa-repeat" role="img" aria-label="Rotate"/></a>
|
||||
</div>
|
||||
<div class="btn-group" role="group">
|
||||
<a role="button" href="#" class="o_viewer_toolbar_btn btn o_print_btn" data-toggle="tooltip" title="Print"><i class="fa fa-fw fa-print" role="img" aria-label="Print"/></a>
|
||||
<a role="button" href="#" class="o_viewer_toolbar_btn btn o_download_btn" data-toggle="tooltip" title="Download"><i class="fa fa-fw fa-download" role="img" aria-label="Download"/></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!--
|
||||
@param {mail.DocumentViewer} widget
|
||||
-->
|
||||
<t t-name="spiffyDocumentViewer">
|
||||
<div class="modal o_modal_fullscreen" id="myModal">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="attch-modal-content h-100">
|
||||
<t class="o_document_viewer_content_call" t-call="spiffyDocumentViewer.Content" />
|
||||
<t t-if="widget.attachment.length !== 1">
|
||||
<a class="arrow arrow-left move_previous" href="#">
|
||||
<span class="fa fa-chevron-left" role="img" aria-label="Previous" title="Previous"/>
|
||||
</a>
|
||||
<a class="arrow arrow-right move_next" href="#">
|
||||
<span class="fa fa-chevron-right" role="img" aria-label="Next" title="Next"/>
|
||||
</a>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="PrintImage">
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
function onload_img() {
|
||||
setTimeout('print_img()', 10);
|
||||
}
|
||||
function print_img() {
|
||||
window.print();
|
||||
window.close();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload='onload_img()'>
|
||||
<img t-att-src='src' alt=""/>
|
||||
</body>
|
||||
</html>
|
||||
</t>
|
||||
</templates>
|
||||
Reference in New Issue
Block a user