466 lines
25 KiB
HTML
466 lines
25 KiB
HTML
<!DOCTYPE html>
|
|
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
|
this repository contains the full copyright notices and license terms. -->
|
|
<html style="overflow: auto;" lang="en" theme="default">
|
|
<head>
|
|
<meta charset="utf-8"/>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
|
|
<title>Tryton</title>
|
|
<link rel="icon" type="image/png" href="images/tradon-icon.png">
|
|
|
|
<script type="text/javascript" src="bower_components/jquery/dist/jquery.js"></script>
|
|
<script type="text/javascript" src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
|
|
<script type="text/javascript" src="bower_components/moment/moment.js"></script>
|
|
<script type="text/javascript" src="bower_components/moment/min/locales.js"></script>
|
|
<script type="text/javascript" src="bower_components/gettext.js/dist/gettext.js"></script>
|
|
<script type="text/javascript" src="bower_components/d3/d3.js"></script>
|
|
<script type="text/javascript" src="bower_components/c3/c3.js"></script>
|
|
<script type="text/javascript" src="bower_components/papaparse/papaparse.js"></script>
|
|
<script type="text/javascript" src="bower_components/fullcalendar/dist/fullcalendar.js"></script>
|
|
<script type="text/javascript" src="bower_components/fullcalendar/dist/locale-all.js"></script>
|
|
<script type="text/javascript" src="bower_components/mousetrap/mousetrap.js"></script>
|
|
<script type="text/javascript" src="bower_components/mousetrap/plugins/pause/mousetrap-pause.js"></script>
|
|
<script type="text/javascript" src="bower_components/Sortable/Sortable.js"></script>
|
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ag-grid-community@31.3.4/dist/ag-grid-community.min.js"></script>
|
|
|
|
<link rel="stylesheet" href="bower_components/c3/c3.css">
|
|
<link rel="stylesheet" href="bower_components/fullcalendar/dist/fullcalendar.css">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ag-grid-community@31.3.4/styles/ag-grid.css">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ag-grid-community@31.3.4/styles/ag-theme-alpine.css">
|
|
|
|
<script type="text/javascript" src="dist/tryton-sao_v1.2.js"></script>
|
|
<link rel="stylesheet" type="text/css" href="dist/tryton-sao_v1.2.css" media="screen"/>
|
|
<script type="text/javascript" src="custom.js"></script>
|
|
<link rel="stylesheet" type="text/css" href="custom.css" media="screen"/>
|
|
<script type="text/javascript">
|
|
(function() {
|
|
try {
|
|
var storedMode = window.localStorage &&
|
|
localStorage.getItem('sao_theme_mode');
|
|
document.documentElement.setAttribute(
|
|
'data-theme-mode',
|
|
storedMode || 'light');
|
|
} catch (error) {
|
|
document.documentElement.setAttribute(
|
|
'data-theme-mode', 'light');
|
|
}
|
|
try {
|
|
var storedDensity = window.localStorage &&
|
|
localStorage.getItem('sao_density_mode');
|
|
document.documentElement.setAttribute(
|
|
'data-density',
|
|
storedDensity || 'compact');
|
|
} catch (error) {
|
|
document.documentElement.setAttribute(
|
|
'data-density', 'compact');
|
|
}
|
|
}());
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<noscript>
|
|
<strong>Sorry sao does not work without JavaScript enabled. Please enable it to continue.</strong>
|
|
</noscript>
|
|
<div class="body" style="display: none;">
|
|
<nav class="navbar navbar-inverse navbar-static-top" role="navigation" style="margin-bottom: 0px;">
|
|
<div class="container-fluid">
|
|
<div class="navbar-header">
|
|
<button type="button" class="navbar-toggle collapsed"
|
|
data-toggle="collapse" data-target="#main_navbar">
|
|
<span class="caret"></span>
|
|
</button>
|
|
<a class="navbar-brand" href="javascript:void(0)" data-toggle="offcanvas">
|
|
<span class="icon">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
|
|
<path d="M0 0h24v24H0z" fill="none"/>
|
|
<path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/>
|
|
</svg>
|
|
</span>
|
|
<span id="title">Tryton</span>
|
|
</a>
|
|
<button type="button" id="theme-mode-toggle"
|
|
class="btn btn-default navbar-btn theme-mode-toggle"
|
|
title="Toggle dark mode"
|
|
aria-label="Toggle dark mode"
|
|
aria-pressed="false">
|
|
<span class="theme-mode-toggle-icon" aria-hidden="true">
|
|
<svg viewBox="0 0 20 20" focusable="false">
|
|
<path d="M10 2.5v2.1"></path>
|
|
<path d="M10 15.4v2.1"></path>
|
|
<path d="M4.7 4.7l1.5 1.5"></path>
|
|
<path d="M13.8 13.8l1.5 1.5"></path>
|
|
<path d="M2.5 10h2.1"></path>
|
|
<path d="M15.4 10h2.1"></path>
|
|
<path d="M4.7 15.3l1.5-1.5"></path>
|
|
<path d="M13.8 6.2l1.5-1.5"></path>
|
|
<circle cx="10" cy="10" r="3.3"></circle>
|
|
</svg>
|
|
</span>
|
|
</button>
|
|
</div>
|
|
<div class="collapse navbar-collapse" id="main_navbar">
|
|
<form class="navbar-form navbar-left flip" role="search" id="global-search" style="border-style: none;">
|
|
</form>
|
|
<ul class="nav navbar-nav navbar-right flip">
|
|
<li id="user-preferences"></li>
|
|
<li id="user-logout">
|
|
<a href="#">
|
|
<span class="icon hidden-xs">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
|
|
<path d="M0 0h24v24H0z" fill="none"/>
|
|
<path d="M10.09 15.59L11.5 17l5-5-5-5-1.41 1.41L12.67 11H3v2h9.67l-2.58 2.59zM19 3H5c-1.11 0-2 .9-2 2v4h2V5h14v14H5v-4H3v4c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/>
|
|
</svg>
|
|
</span>
|
|
<span class="visible-xs">
|
|
</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
<ul id="tablist" class="nav navbar-nav nav-pills" role="tablist">
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
<div id="main" class="container-fluid" style="padding: 0px;">
|
|
<div id="tradon-full-menu" class="tradon-full-menu" aria-hidden="true">
|
|
<div class="tradon-full-menu-grid"></div>
|
|
</div>
|
|
<div class="row row-offcanvas row-offcanvas-left active"
|
|
style="height: calc(100vh - 50px - 1px - 20px); margin: 0px;">
|
|
<div class="col-xs-12 col-sm-4 col-lg-3 sidebar-offcanvas" id="menu" role="navigation"
|
|
style="overflow-y: auto; height: 100%;"></div>
|
|
<div class="col-xs-12 col-sm-8 col-lg-9 main-offcanvas" style="display:flex; overflow-y: auto; height: 100%;" id="tabs" role="tabpanel">
|
|
<div id="tabcontent" class="tab-content"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script type="text/javascript">
|
|
if ((typeof jQuery == 'undefined') || (typeof Sao == 'undefined')) {
|
|
document.querySelector('body').innerHTML = '<strong>sao is not fully installed. Please refer to <a href="README.md">README</a></strong>';
|
|
} else {
|
|
jQuery(function() {
|
|
function applyThemeMode(mode) {
|
|
var isDark = mode === 'dark';
|
|
document.documentElement.setAttribute(
|
|
'data-theme-mode', isDark ? 'dark' : 'light');
|
|
try {
|
|
if (window.localStorage) {
|
|
localStorage.setItem(
|
|
'sao_theme_mode', isDark ? 'dark' : 'light');
|
|
}
|
|
} catch (error) {
|
|
}
|
|
var toggle = jQuery('#theme-mode-toggle');
|
|
toggle.attr('aria-pressed', isDark ? 'true' : 'false');
|
|
toggle.attr(
|
|
'title',
|
|
isDark ? 'Switch to light mode' :
|
|
'Switch to dark mode');
|
|
var logo = jQuery('#title-logo');
|
|
if (logo.length) {
|
|
logo.attr(
|
|
'src',
|
|
'dist/tradon_wbg.png');
|
|
logo.attr('title', 'v1.2');
|
|
}
|
|
}
|
|
|
|
jQuery('#theme-mode-toggle').click(function() {
|
|
var current = document.documentElement.getAttribute(
|
|
'data-theme-mode');
|
|
applyThemeMode(current === 'dark' ? 'light' : 'dark');
|
|
});
|
|
|
|
applyThemeMode(
|
|
document.documentElement.getAttribute('data-theme-mode'));
|
|
jQuery('.body').show();
|
|
function notifyLayoutResize() {
|
|
[0, 80, 180, 320].forEach(function(delay) {
|
|
window.setTimeout(function() {
|
|
window.dispatchEvent(new Event('resize'));
|
|
}, delay);
|
|
});
|
|
}
|
|
// Keep the full-screen menu code in place, but disable its
|
|
// loading and logo entry point while the layout is refined.
|
|
var enableFullMenu = false;
|
|
function setFullMenuVisible(visible) {
|
|
var main = jQuery('#main');
|
|
if (visible && !jQuery('#tradon-full-menu')
|
|
.find('.tradon-full-menu-card').length) {
|
|
visible = false;
|
|
}
|
|
jQuery('#tradon-full-menu').attr(
|
|
'aria-hidden', visible ? 'false' : 'true');
|
|
main.toggleClass('tradon-full-menu-active', visible);
|
|
if (visible) {
|
|
jQuery('.row-offcanvas').removeClass('active');
|
|
}
|
|
notifyLayoutResize();
|
|
}
|
|
function normalizeMenuValue(value) {
|
|
if (value === null || value === undefined) {
|
|
return '';
|
|
}
|
|
if (Array.isArray(value)) {
|
|
return value.length > 1 ? value[1] : value[0];
|
|
}
|
|
if (typeof value == 'object') {
|
|
return value.rec_name || value.name || '';
|
|
}
|
|
return value;
|
|
}
|
|
function menuField(record, name) {
|
|
if (name == 'rec_name' && record._values &&
|
|
record._values.rec_name) {
|
|
return record._values.rec_name;
|
|
}
|
|
try {
|
|
if (record.model && record.model.fields[name]) {
|
|
return normalizeMenuValue(
|
|
record.field_get_client(name));
|
|
}
|
|
} catch (error) {
|
|
}
|
|
return null;
|
|
}
|
|
function menuLabel(record) {
|
|
return menuField(record, 'name') ||
|
|
menuField(record, 'rec_name') ||
|
|
(record.id ? String(record.id) : '');
|
|
}
|
|
function prepareMenuRecord(record) {
|
|
var waits = [];
|
|
['name', 'icon'].forEach(function(name) {
|
|
if (record.model && record.model.fields[name] &&
|
|
!record.is_loaded(name)) {
|
|
waits.push(record.load(name, true, false));
|
|
}
|
|
});
|
|
if (!record._values || !record._values.rec_name) {
|
|
waits.push(record.rec_name().then(
|
|
function(name) {
|
|
record._values.rec_name = name;
|
|
},
|
|
function() {
|
|
}));
|
|
}
|
|
return jQuery.when.apply(jQuery, waits);
|
|
}
|
|
function activateMenuRecord(record) {
|
|
if (Sao.main_menu_screen) {
|
|
Sao.main_menu_screen.current_record = record;
|
|
setFullMenuVisible(false);
|
|
Sao.main_menu_row_activate();
|
|
}
|
|
}
|
|
function loadMenuChildren(record, childrenField) {
|
|
if (!childrenField) {
|
|
return jQuery.when([]);
|
|
}
|
|
var load = record.is_loaded &&
|
|
record.is_loaded(childrenField) ?
|
|
jQuery.when() :
|
|
record.load(childrenField, true, false);
|
|
return load.then(function() {
|
|
return record.field_get_client(childrenField) || [];
|
|
});
|
|
}
|
|
function buildMenuNode(record, childrenField, depth) {
|
|
return prepareMenuRecord(record).then(function() {
|
|
var node = {
|
|
label: menuLabel(record),
|
|
icon: menuField(record, 'icon'),
|
|
record: record,
|
|
children: []
|
|
};
|
|
if (depth > 4) {
|
|
return node;
|
|
}
|
|
return loadMenuChildren(record, childrenField)
|
|
.then(function(children) {
|
|
var waits = [];
|
|
children.forEach(function(child) {
|
|
waits.push(buildMenuNode(
|
|
child, childrenField, depth + 1));
|
|
});
|
|
return jQuery.when.apply(jQuery, waits)
|
|
.then(function() {
|
|
node.children = Array.prototype.slice
|
|
.call(arguments);
|
|
return node;
|
|
});
|
|
});
|
|
});
|
|
}
|
|
function appendMenuLink(container, node, level) {
|
|
var link = jQuery('<button/>', {
|
|
'type': 'button',
|
|
'class': 'tradon-full-menu-link level-' + level,
|
|
'title': node.label,
|
|
'text': node.label
|
|
}).click(function() {
|
|
activateMenuRecord(node.record);
|
|
});
|
|
container.append(link);
|
|
}
|
|
function appendMenuBranch(container, node, level) {
|
|
appendMenuLink(container, node, level);
|
|
if (level >= 3) {
|
|
return;
|
|
}
|
|
node.children.slice(0, 4).forEach(function(child) {
|
|
appendMenuBranch(container, child, level + 1);
|
|
});
|
|
}
|
|
function renderMenuCard(grid, node, index) {
|
|
if (!node || !node.label) {
|
|
return;
|
|
}
|
|
var card = jQuery('<section/>', {
|
|
'class': 'tradon-full-menu-card'
|
|
}).appendTo(grid);
|
|
var header = jQuery('<button/>', {
|
|
'type': 'button',
|
|
'class': 'tradon-full-menu-card-title',
|
|
'title': node.label
|
|
}).click(function() {
|
|
activateMenuRecord(node.record);
|
|
}).appendTo(card);
|
|
if (node.icon) {
|
|
Sao.common.ICONFACTORY.get_icon_url(node.icon)
|
|
.then(function(url) {
|
|
jQuery('<img/>', {
|
|
'class': 'tradon-full-menu-icon',
|
|
'src': url,
|
|
'alt': ''
|
|
}).prependTo(header);
|
|
});
|
|
}
|
|
jQuery('<span/>', {'text': node.label}).appendTo(header);
|
|
var content = jQuery('<div/>', {
|
|
'class': 'tradon-full-menu-card-content'
|
|
}).appendTo(card);
|
|
var children = node.children || [];
|
|
if (children.length > 5) {
|
|
var tabs = jQuery('<div/>', {
|
|
'class': 'tradon-full-menu-tabs'
|
|
}).appendTo(content);
|
|
children.slice(0, 4).forEach(function(child, tabIndex) {
|
|
var tab = jQuery('<button/>', {
|
|
'type': 'button',
|
|
'class': 'tradon-full-menu-tab' +
|
|
(tabIndex ? '' : ' active'),
|
|
'text': child.label,
|
|
'title': child.label
|
|
}).appendTo(tabs);
|
|
tab.click(function() {
|
|
tabs.children().removeClass('active');
|
|
tab.addClass('active');
|
|
links.empty();
|
|
appendMenuBranch(links, child, 1);
|
|
});
|
|
});
|
|
var links = jQuery('<div/>', {
|
|
'class': 'tradon-full-menu-links'
|
|
}).appendTo(content);
|
|
appendMenuBranch(links, children[0], 1);
|
|
} else {
|
|
var plainLinks = jQuery('<div/>', {
|
|
'class': 'tradon-full-menu-links'
|
|
}).appendTo(content);
|
|
children.forEach(function(child) {
|
|
appendMenuBranch(plainLinks, child, 1);
|
|
});
|
|
}
|
|
}
|
|
function rebuildFullMenu() {
|
|
var screen = Sao.main_menu_screen;
|
|
var view = screen && screen.current_view;
|
|
var grid = jQuery('#tradon-full-menu .tradon-full-menu-grid');
|
|
var records = [];
|
|
if (view && view.rows && view.rows.length) {
|
|
records = view.rows.map(function(row) {
|
|
return row.record;
|
|
});
|
|
} else if (screen && screen.group && screen.group.length) {
|
|
records = screen.group.slice(0);
|
|
}
|
|
if (!view || !records.length) {
|
|
return jQuery.when(false);
|
|
}
|
|
grid.empty();
|
|
var waits = records.map(function(record) {
|
|
return buildMenuNode(record, view.children_field, 0);
|
|
});
|
|
return jQuery.when.apply(jQuery, waits).then(function() {
|
|
var nodes = Array.prototype.slice.call(arguments);
|
|
grid.empty();
|
|
nodes.forEach(function(node, index) {
|
|
renderMenuCard(grid, node, index);
|
|
});
|
|
return Boolean(grid.children().length);
|
|
});
|
|
}
|
|
function showFullMenuWhenReady(attempt) {
|
|
if (!enableFullMenu) {
|
|
setFullMenuVisible(false);
|
|
return;
|
|
}
|
|
attempt = attempt || 0;
|
|
rebuildFullMenu().then(
|
|
function(ready) {
|
|
if (ready) {
|
|
setFullMenuVisible(true);
|
|
} else if (attempt < 8) {
|
|
window.setTimeout(function() {
|
|
showFullMenuWhenReady(attempt + 1);
|
|
}, 120);
|
|
} else {
|
|
setFullMenuVisible(false);
|
|
}
|
|
},
|
|
function() {
|
|
setFullMenuVisible(false);
|
|
});
|
|
}
|
|
jQuery(document).on('tradon:main-menu-ready', function() {
|
|
if (!enableFullMenu) {
|
|
setFullMenuVisible(false);
|
|
return;
|
|
}
|
|
showFullMenuWhenReady(0);
|
|
});
|
|
jQuery('[data-toggle="offcanvas"]').click(function(event) {
|
|
if (enableFullMenu &&
|
|
jQuery(event.target).closest('#title-logo').length) {
|
|
if (jQuery('#main').hasClass(
|
|
'tradon-full-menu-active')) {
|
|
setFullMenuVisible(false);
|
|
} else {
|
|
showFullMenuWhenReady(0);
|
|
}
|
|
return false;
|
|
}
|
|
setFullMenuVisible(false);
|
|
jQuery('.row-offcanvas').toggleClass('active');
|
|
notifyLayoutResize();
|
|
});
|
|
jQuery('#tabs').on('ready', function() {
|
|
var mq = window.matchMedia('(max-width: 991px)');
|
|
if (mq.matches) {
|
|
if (jQuery('#tablist').children().length) {
|
|
jQuery('.row-offcanvas').removeClass('active');
|
|
} else {
|
|
jQuery('.row-offcanvas').addClass('active');
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|