UI enhancements
This commit is contained in:
2
.codex/config.toml
Normal file
2
.codex/config.toml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
approval_policy = "never"
|
||||||
|
sandbox_mode = "danger-full-access"
|
||||||
BIN
dist/tradon_wbg.png
vendored
Normal file
BIN
dist/tradon_wbg.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 124 KiB |
3346
dist/tryton-sao.css
vendored
3346
dist/tryton-sao.css
vendored
File diff suppressed because it is too large
Load Diff
2191
dist/tryton-sao.js
vendored
2191
dist/tryton-sao.js
vendored
File diff suppressed because it is too large
Load Diff
16612
dist/tryton-sao_v1.2.css
vendored
Normal file
16612
dist/tryton-sao_v1.2.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
38715
dist/tryton-sao_v1.2.js
vendored
Normal file
38715
dist/tryton-sao_v1.2.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
284
index.html
284
index.html
@@ -29,8 +29,8 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
<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-grid.css">
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ag-grid-community@31.3.4/styles/ag-theme-alpine.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.js"></script>
|
<script type="text/javascript" src="dist/tryton-sao_v1.2.js"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="dist/tryton-sao.css" media="screen"/>
|
<link rel="stylesheet" type="text/css" href="dist/tryton-sao_v1.2.css" media="screen"/>
|
||||||
<script type="text/javascript" src="custom.js"></script>
|
<script type="text/javascript" src="custom.js"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="custom.css" media="screen"/>
|
<link rel="stylesheet" type="text/css" href="custom.css" media="screen"/>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
@@ -45,6 +45,16 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
document.documentElement.setAttribute(
|
document.documentElement.setAttribute(
|
||||||
'data-theme-mode', 'light');
|
'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>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
@@ -113,6 +123,9 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<div id="main" class="container-fluid" style="padding: 0px;">
|
<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"
|
<div class="row row-offcanvas row-offcanvas-left active"
|
||||||
style="height: calc(100vh - 50px - 1px - 20px); margin: 0px;">
|
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"
|
<div class="col-xs-12 col-sm-4 col-lg-3 sidebar-offcanvas" id="menu" role="navigation"
|
||||||
@@ -149,8 +162,8 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
if (logo.length) {
|
if (logo.length) {
|
||||||
logo.attr(
|
logo.attr(
|
||||||
'src',
|
'src',
|
||||||
isDark ? 'dist/tradon-dark.png' :
|
'dist/tradon_wbg.png');
|
||||||
'dist/tradon.png');
|
logo.attr('title', 'v1.2');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +183,268 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
}, delay);
|
}, delay);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
jQuery('[data-toggle="offcanvas"]').click(function() {
|
// 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');
|
jQuery('.row-offcanvas').toggleClass('active');
|
||||||
notifyLayoutResize();
|
notifyLayoutResize();
|
||||||
});
|
});
|
||||||
|
|||||||
BIN
tradon_wbg.png
Normal file
BIN
tradon_wbg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 124 KiB |
3291
tryton-sao.css
3291
tryton-sao.css
File diff suppressed because it is too large
Load Diff
2191
tryton-sao.js
2191
tryton-sao.js
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user