Notes
This commit is contained in:
@@ -962,6 +962,21 @@ Point de deploiement:
|
|||||||
- correctif final: `_force_horizontal_scroll_width()` additionne maintenant les largeurs reelles `getActualWidth()` et ne modifie plus jamais les largeurs de colonnes
|
- correctif final: `_force_horizontal_scroll_width()` additionne maintenant les largeurs reelles `getActualWidth()` et ne modifie plus jamais les largeurs de colonnes
|
||||||
- invariant: une fonction de scrollbar peut dimensionner le conteneur de scroll, mais ne doit jamais changer la taille des colonnes utilisateur
|
- invariant: une fonction de scrollbar peut dimensionner le conteneur de scroll, mais ne doit jamais changer la taille des colonnes utilisateur
|
||||||
|
|
||||||
|
### A faire - tri en mode grouping AG Grid
|
||||||
|
|
||||||
|
- demande UX: permettre `asc` / `desc` / aucun tri sur les colonnes meme quand le grouping AG Grid manuel est actif
|
||||||
|
- la configuration de vue doit memoriser ce tri, comme les colonnes, filtres checklist, `valueFilters` et grouping
|
||||||
|
- point de vigilance majeur: ne pas simplement remettre `sortable: true` avec le tri natif AG Grid sur le `rowData` groupe
|
||||||
|
- raison: le grouping est construit manuellement dans `_flatten_grouped_rows()` avec lignes `group`, `record`, `total`; un tri natif AG Grid apres coup peut separer les records de leurs groupes ou deplacer sous-totaux/totaux
|
||||||
|
- approche recommandee:
|
||||||
|
- capturer l'intention de tri utilisateur dans l'etat de vue
|
||||||
|
- trier les records source avant `_flatten_grouped_rows()`
|
||||||
|
- pour une colonne de grouping, trier l'ordre des groupes a ce niveau
|
||||||
|
- pour une colonne non groupee, trier les records a l'interieur des groupes
|
||||||
|
- reconstruire ensuite `rowData` en preservant `expandedPaths`, sous-totaux, grand total et filtres checklist actifs
|
||||||
|
- invariant: en mode grouping, AG Grid ne doit jamais trier directement les lignes deja groupees; SAO doit trier les records avant construction des groupes
|
||||||
|
- tests a prevoir: asc/desc/none, colonne groupee, colonne non groupee, groupes ouverts/fermes, sous-totaux, grand total, filtres checklist actifs, sauvegarde/restauration de preset, retour a `Default view`
|
||||||
|
|
||||||
### Correctif largeur formulaire avec menu gauche masque
|
### Correctif largeur formulaire avec menu gauche masque
|
||||||
|
|
||||||
- bug observe: dans la forme Purchase/contrat, meme menu gauche cache, le formulaire ne s'etirait plus sur toute la largeur; il restait visuellement autour de 75% de l'ecran
|
- bug observe: dans la forme Purchase/contrat, meme menu gauche cache, le formulaire ne s'etirait plus sur toute la largeur; il restait visuellement autour de 75% de l'ecran
|
||||||
@@ -972,6 +987,16 @@ Point de deploiement:
|
|||||||
- fichiers modifies: toujours synchroniser `tryton-sao.css` et `dist/tryton-sao.css`, car `index.html` charge le CSS depuis `dist/`
|
- fichiers modifies: toujours synchroniser `tryton-sao.css` et `dist/tryton-sao.css`, car `index.html` charge le CSS depuis `dist/`
|
||||||
- lecon: apres un correctif AG Grid/offcanvas, tester les deux etats du hamburger; menu visible, la zone centrale doit rester en colonne Bootstrap, menu cache, elle doit redevenir pleine largeur
|
- lecon: apres un correctif AG Grid/offcanvas, tester les deux etats du hamburger; menu visible, la zone centrale doit rester en colonne Bootstrap, menu cache, elle doit redevenir pleine largeur
|
||||||
|
|
||||||
|
### Invariant critique scroll AG Grid vs formulaire classique
|
||||||
|
|
||||||
|
- regression observee apres les essais de scroll vertical AG Grid: une forme Purchase classique, sans AG Grid principale, etait coupee verticalement et mal redimensionnee, avec ou sans menu gauche
|
||||||
|
- cause reelle: `_resize_grid_host()` pose des dimensions inline sur le `content_box` quand il contient une AG Grid (`height`, `minHeight`, `flexBasis`, `flexShrink`, `width`, `maxWidth`); si le meme `content_box` est ensuite reutilise pour une forme classique, ces styles inline peuvent survivre apres retrait de la classe `ag-grid-content-box`
|
||||||
|
- autre cause dangereuse: ne jamais mettre `overflow-y: hidden` sur `.screen-container` ou sur un conteneur commun pour supprimer le scroll SAO; cela casse les formulaires classiques et les sous-listes embarquees
|
||||||
|
- correctif cle: dans `Sao.ScreenContainer.set`, quand `is_ag_grid` est faux, nettoyer explicitement les dimensions inline du `content_box` avant d'ajouter le widget classique
|
||||||
|
- invariant: les adaptations de scroll AG Grid doivent etre strictement limitees a `.content-box.ag-grid-content-box` et aux conteneurs internes AG Grid; une fiche formulaire doit garder `.content-box` en `flex: 1 1 auto` avec `overflow-y: auto`
|
||||||
|
- test obligatoire apres toute retouche layout/scroll: ouvrir une forme Purchase sans AG Grid principale, menu gauche ouvert puis cache; verifier que le formulaire descend jusqu'aux onglets/lignes et que la zone centrale se redimensionne correctement
|
||||||
|
- test complementaire: ouvrir Lots Management ou une vue report AG Grid avec filtres hauts; verifier que le scroll vertical utile reste celui de l'AG Grid et que le conteneur SAO ne cree pas un deuxieme scroll parasite
|
||||||
|
|
||||||
### Commits importants
|
### Commits importants
|
||||||
|
|
||||||
- `fc9ab5d Save SAO AG Grid work`
|
- `fc9ab5d Save SAO AG Grid work`
|
||||||
|
|||||||
@@ -322,6 +322,7 @@ Traces a lire si le sujet revient:
|
|||||||
- resize colonnes: ne jamais utiliser la largeur par defaut metier comme `minWidth`; `_get_default_column_width()` sert au premier affichage, `_get_minimum_column_width()` sert au resize et aux corrections de vieux states
|
- resize colonnes: ne jamais utiliser la largeur par defaut metier comme `minWidth`; `_get_default_column_width()` sert au premier affichage, `_get_minimum_column_width()` sert au resize et aux corrections de vieux states
|
||||||
- resize colonnes: ne pas lancer le refresh layout global depuis `onColumnResized`; annuler les timers pendant le drag et sauver la largeur avec `skipLayoutRefresh`, sinon `doLayout()` peut annuler la largeur choisie par l'utilisateur
|
- resize colonnes: ne pas lancer le refresh layout global depuis `onColumnResized`; annuler les timers pendant le drag et sauver la largeur avec `skipLayoutRefresh`, sinon `doLayout()` peut annuler la largeur choisie par l'utilisateur
|
||||||
- resize colonnes: `_force_horizontal_scroll_width()` ne doit jamais appeler `setColumnWidth()`; calculer le scroll avec `getActualWidth()` pour respecter les largeurs utilisateur
|
- resize colonnes: `_force_horizontal_scroll_width()` ne doit jamais appeler `setColumnWidth()`; calculer le scroll avec `getActualWidth()` pour respecter les largeurs utilisateur
|
||||||
|
- futur tri en mode grouping: autoriser asc/desc/none et le memoriser dans la config de vue, mais ne pas reactiver le tri natif AG Grid sur le `rowData` groupe; capturer l'intention, trier les records source avant `_flatten_grouped_rows()`, puis reconstruire les lignes `group`/`record`/`total` en preservant expansions, totaux et filtres checklist actifs
|
||||||
|
|
||||||
### AG Grid - règles d'or
|
### AG Grid - règles d'or
|
||||||
|
|
||||||
@@ -339,3 +340,10 @@ Traces a lire si le sujet revient:
|
|||||||
- correctif: `.row-offcanvas:not(.active) .main-offcanvas` force `float: none`, `flex: 0 0 100%`, `width: 100%`, `max-width: 100%`
|
- correctif: `.row-offcanvas:not(.active) .main-offcanvas` force `float: none`, `flex: 0 0 100%`, `width: 100%`, `max-width: 100%`
|
||||||
- complement: `.screen-container` force `min-width: 0`, `width: 100%`, `max-width: 100%`
|
- complement: `.screen-container` force `min-width: 0`, `width: 100%`, `max-width: 100%`
|
||||||
- verifier apres ce type de retouche: menu gauche ouvert et cache, formulaire classique, vue tree AG Grid, et toujours synchroniser `dist/tryton-sao.css`
|
- verifier apres ce type de retouche: menu gauche ouvert et cache, formulaire classique, vue tree AG Grid, et toujours synchroniser `dist/tryton-sao.css`
|
||||||
|
|
||||||
|
### Invariant critique scroll/layout AG Grid
|
||||||
|
|
||||||
|
- ne jamais supprimer le scroll vertical SAO au niveau `.screen-container`; limiter les overrides de scroll a `.content-box.ag-grid-content-box`
|
||||||
|
- `_resize_grid_host()` peut poser des styles inline sur le `content_box`; quand `Sao.ScreenContainer.set()` repasse sur un widget non AG Grid, nettoyer `height`, `minHeight`, `flexBasis`, `flexShrink`, `width`, `maxWidth`
|
||||||
|
- regression typique si cet invariant casse: forme Purchase classique coupee en bas, onglets/lignes mal visibles, grande zone blanche ou largeur incorrecte apres toggle du menu gauche
|
||||||
|
- test obligatoire: Purchase form sans AG Grid principale avec menu gauche ouvert/cache, puis Lots Management/report AG Grid avec filtres hauts
|
||||||
|
|||||||
57
dist/tryton-sao.css
vendored
57
dist/tryton-sao.css
vendored
@@ -9685,6 +9685,48 @@ img.icon {
|
|||||||
.filter-box {
|
.filter-box {
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
}
|
}
|
||||||
|
.ag-grid-screen-filter-toggle-bar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
margin: 0 0 5px;
|
||||||
|
}
|
||||||
|
.ag-grid-tree-toolbar > .ag-grid-screen-filter-toggle-bar {
|
||||||
|
margin: 0 10px 0 auto;
|
||||||
|
}
|
||||||
|
.ag-grid-screen-filter-toggle {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 7px;
|
||||||
|
min-height: 30px;
|
||||||
|
padding: 4px 10px;
|
||||||
|
border: 1px solid #d6e4df;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: linear-gradient(180deg, #f6fbf9 0%, #edf5f1 100%);
|
||||||
|
color: #355154;
|
||||||
|
box-shadow: 0 2px 7px rgba(53, 81, 84, 0.1);
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.2;
|
||||||
|
text-transform: none !important;
|
||||||
|
transition: background-color 0.18s ease, border-color 0.18s ease,
|
||||||
|
box-shadow 0.18s ease, transform 0.18s ease;
|
||||||
|
}
|
||||||
|
.ag-grid-screen-filter-toggle:hover,
|
||||||
|
.ag-grid-screen-filter-toggle:focus {
|
||||||
|
background: linear-gradient(180deg, #f2faf7 0%, #e7f2ed 100%);
|
||||||
|
border-color: #bfd5cd;
|
||||||
|
color: #28484b;
|
||||||
|
box-shadow: 0 3px 9px rgba(53, 81, 84, 0.13);
|
||||||
|
}
|
||||||
|
.ag-grid-screen-filter-toggle:active {
|
||||||
|
transform: translateY(1px);
|
||||||
|
box-shadow: 0 1px 5px rgba(53, 81, 84, 0.1);
|
||||||
|
}
|
||||||
|
.ag-grid-screen-filter-toggle .icon {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
opacity: 0.78;
|
||||||
|
}
|
||||||
@media screen and (max-width: 991px) {
|
@media screen and (max-width: 991px) {
|
||||||
.filter-box button[disabled] {
|
.filter-box button[disabled] {
|
||||||
display: none;
|
display: none;
|
||||||
@@ -9696,6 +9738,13 @@ img.icon {
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
.content-box:not(.ag-grid-content-box) {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
height: auto;
|
||||||
|
min-height: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: visible;
|
||||||
|
}
|
||||||
.content-box.ag-grid-content-box {
|
.content-box.ag-grid-content-box {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
@@ -10788,10 +10837,10 @@ body {
|
|||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
.row-offcanvas:not(.active) .main-offcanvas {
|
.row-offcanvas:not(.active) .main-offcanvas {
|
||||||
float: none;
|
float: none !important;
|
||||||
flex: 0 0 100%;
|
flex: 0 0 100% !important;
|
||||||
width: 100%;
|
width: 100% !important;
|
||||||
max-width: 100%;
|
max-width: 100% !important;
|
||||||
}
|
}
|
||||||
.sidebar-offcanvas {
|
.sidebar-offcanvas {
|
||||||
position: absolute !important;
|
position: absolute !important;
|
||||||
|
|||||||
125
dist/tryton-sao.js
vendored
125
dist/tryton-sao.js
vendored
@@ -1278,6 +1278,11 @@ var Sao = {
|
|||||||
Mousetrap.bind(['ctrl+m', 'command+m'], function(e) {
|
Mousetrap.bind(['ctrl+m', 'command+m'], function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
jQuery('.row-offcanvas').toggleClass('active');
|
jQuery('.row-offcanvas').toggleClass('active');
|
||||||
|
[0, 80, 180, 320].forEach(function(delay) {
|
||||||
|
window.setTimeout(function() {
|
||||||
|
window.dispatchEvent(new Event('resize'));
|
||||||
|
}, delay);
|
||||||
|
});
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -12422,6 +12427,23 @@ var Sao = {
|
|||||||
'class': 'row'
|
'class': 'row'
|
||||||
}).appendTo(this.filter_box);
|
}).appendTo(this.filter_box);
|
||||||
this.el.append(this.filter_box);
|
this.el.append(this.filter_box);
|
||||||
|
this.ag_grid_filter_toggle_bar = jQuery('<div/>', {
|
||||||
|
'class': 'ag-grid-screen-filter-toggle-bar',
|
||||||
|
}).hide();
|
||||||
|
this.ag_grid_filter_toggle = jQuery('<button/>', {
|
||||||
|
'type': 'button',
|
||||||
|
'class': 'btn btn-default btn-sm ag-grid-screen-filter-toggle',
|
||||||
|
'aria-expanded': 'true',
|
||||||
|
'title': Sao.i18n.gettext('Hide filters'),
|
||||||
|
}).append(Sao.common.ICONFACTORY.get_icon_img('tryton-unfold-less', {
|
||||||
|
'aria-hidden': true,
|
||||||
|
})).append(jQuery('<span/>', {
|
||||||
|
'class': 'ag-grid-screen-filter-toggle-label',
|
||||||
|
'text': ' ' + Sao.i18n.gettext('Hide filters'),
|
||||||
|
})).appendTo(this.ag_grid_filter_toggle_bar);
|
||||||
|
this.ag_grid_filter_toggle.click(
|
||||||
|
this.toggle_ag_grid_filters.bind(this));
|
||||||
|
this.el.append(this.ag_grid_filter_toggle_bar);
|
||||||
this.filter_button = jQuery('<button/>', {
|
this.filter_button = jQuery('<button/>', {
|
||||||
type: 'button',
|
type: 'button',
|
||||||
'class': 'btn btn-link',
|
'class': 'btn btn-link',
|
||||||
@@ -12802,17 +12824,83 @@ var Sao = {
|
|||||||
this.tab.hide();
|
this.tab.hide();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
toggle_ag_grid_filters: function() {
|
||||||
|
this.set_ag_grid_filters_collapsed(
|
||||||
|
!this.el.hasClass('ag-grid-screen-filters-collapsed'));
|
||||||
|
},
|
||||||
|
set_ag_grid_filters_collapsed: function(collapsed) {
|
||||||
|
this.el.toggleClass('ag-grid-screen-filters-collapsed', collapsed);
|
||||||
|
if (collapsed) {
|
||||||
|
this.filter_box.hide();
|
||||||
|
} else {
|
||||||
|
this.filter_box.show();
|
||||||
|
}
|
||||||
|
if (this.ag_grid_filter_toggle) {
|
||||||
|
this.ag_grid_filter_toggle
|
||||||
|
.attr('aria-expanded', String(!collapsed))
|
||||||
|
.attr('title', Sao.i18n.gettext(
|
||||||
|
collapsed ? 'Show filters' : 'Hide filters'));
|
||||||
|
this.ag_grid_filter_toggle
|
||||||
|
.find('img.icon')
|
||||||
|
.replaceWith(Sao.common.ICONFACTORY.get_icon_img(
|
||||||
|
collapsed ? 'tryton-unfold-more' :
|
||||||
|
'tryton-unfold-less', {
|
||||||
|
'aria-hidden': true,
|
||||||
|
}));
|
||||||
|
this.ag_grid_filter_toggle
|
||||||
|
.find('.ag-grid-screen-filter-toggle-label')
|
||||||
|
.text(' ' + Sao.i18n.gettext(
|
||||||
|
collapsed ? 'Show filters' : 'Hide filters'));
|
||||||
|
}
|
||||||
|
window.setTimeout(() => {
|
||||||
|
window.dispatchEvent(new Event('resize'));
|
||||||
|
}, 0);
|
||||||
|
},
|
||||||
|
set_ag_grid_filter_toggle_visible: function(visible) {
|
||||||
|
if (!this.ag_grid_filter_toggle_bar) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.el.toggleClass('ag-grid-screen-with-filter-toggle', visible);
|
||||||
|
if (visible) {
|
||||||
|
this.ag_grid_filter_toggle_bar.show();
|
||||||
|
this.set_ag_grid_filters_collapsed(
|
||||||
|
this.el.hasClass('ag-grid-screen-filters-collapsed'));
|
||||||
|
} else {
|
||||||
|
this.ag_grid_filter_toggle_bar.hide();
|
||||||
|
this.el.removeClass('ag-grid-screen-filters-collapsed');
|
||||||
|
}
|
||||||
|
},
|
||||||
set: function(widget) {
|
set: function(widget) {
|
||||||
if (this.alternate_view) {
|
if (this.alternate_view) {
|
||||||
this.alternate_viewport.children().detach();
|
this.alternate_viewport.children().detach();
|
||||||
this.alternate_viewport.append(widget);
|
this.alternate_viewport.append(widget);
|
||||||
} else {
|
} else {
|
||||||
|
var is_ag_grid = Boolean(widget && widget.hasClass &&
|
||||||
|
widget.hasClass('ag-grid-tree-container'));
|
||||||
this.content_box.children().detach();
|
this.content_box.children().detach();
|
||||||
this.content_box.toggleClass(
|
this.content_box.toggleClass(
|
||||||
'ag-grid-content-box',
|
'ag-grid-content-box',
|
||||||
Boolean(widget && widget.hasClass &&
|
is_ag_grid);
|
||||||
widget.hasClass('ag-grid-tree-container')));
|
if (!is_ag_grid) {
|
||||||
|
this.content_box.css({
|
||||||
|
height: '',
|
||||||
|
minHeight: '',
|
||||||
|
flexBasis: '',
|
||||||
|
flexShrink: '',
|
||||||
|
width: '',
|
||||||
|
maxWidth: '',
|
||||||
|
});
|
||||||
|
}
|
||||||
this.content_box.append(widget);
|
this.content_box.append(widget);
|
||||||
|
if (is_ag_grid) {
|
||||||
|
var toolbar = widget.find('.ag-grid-tree-toolbar').first();
|
||||||
|
if (toolbar.length) {
|
||||||
|
toolbar.append(this.ag_grid_filter_toggle_bar);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.el.append(this.ag_grid_filter_toggle_bar);
|
||||||
|
}
|
||||||
|
this.set_ag_grid_filter_toggle_visible(is_ag_grid);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
get_text: function() {
|
get_text: function() {
|
||||||
@@ -26393,11 +26481,35 @@ function eval_pyson(value){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var rect = this.grid_host[0].getBoundingClientRect();
|
var rect = this.grid_host[0].getBoundingClientRect();
|
||||||
var available = window.innerHeight - rect.top - 36;
|
|
||||||
var height = Math.max(420, Math.min(720, available));
|
|
||||||
height = Math.max(520, height);
|
|
||||||
var content_box = this.grid_host.closest('.content-box.ag-grid-content-box');
|
var content_box = this.grid_host.closest('.content-box.ag-grid-content-box');
|
||||||
var screen_container = this.grid_host.closest('.screen-container');
|
var screen_container = this.grid_host.closest('.screen-container');
|
||||||
|
var toolbar_height = this.toolbar && this.toolbar.length ?
|
||||||
|
Math.ceil(this.toolbar.outerHeight(true)) : 0;
|
||||||
|
var external_scroll_height = 20;
|
||||||
|
var bottom_margin = 96;
|
||||||
|
var available = window.innerHeight - rect.top -
|
||||||
|
external_scroll_height - bottom_margin;
|
||||||
|
if (content_box.length) {
|
||||||
|
var content_rect = content_box[0].getBoundingClientRect();
|
||||||
|
available = Math.min(
|
||||||
|
available,
|
||||||
|
window.innerHeight - content_rect.top - toolbar_height -
|
||||||
|
external_scroll_height - bottom_margin);
|
||||||
|
}
|
||||||
|
var compact_min_height = 260;
|
||||||
|
var readable_min_height = 420;
|
||||||
|
var maximum_height = 720;
|
||||||
|
var height;
|
||||||
|
if (available >= compact_min_height) {
|
||||||
|
height = Math.max(
|
||||||
|
compact_min_height,
|
||||||
|
Math.min(maximum_height, available));
|
||||||
|
} else {
|
||||||
|
height = Math.max(
|
||||||
|
readable_min_height,
|
||||||
|
Math.min(maximum_height,
|
||||||
|
window.innerHeight - rect.top - bottom_margin));
|
||||||
|
}
|
||||||
var width_right = window.innerWidth - 12;
|
var width_right = window.innerWidth - 12;
|
||||||
if (screen_container.length) {
|
if (screen_container.length) {
|
||||||
width_right = Math.min(
|
width_right = Math.min(
|
||||||
@@ -26413,9 +26525,6 @@ function eval_pyson(value){
|
|||||||
width: available_width + 'px',
|
width: available_width + 'px',
|
||||||
maxWidth: available_width + 'px',
|
maxWidth: available_width + 'px',
|
||||||
});
|
});
|
||||||
var toolbar_height = this.toolbar && this.toolbar.length ?
|
|
||||||
Math.ceil(this.toolbar.outerHeight(true)) : 0;
|
|
||||||
var external_scroll_height = 20;
|
|
||||||
var container_height = height + toolbar_height + external_scroll_height;
|
var container_height = height + toolbar_height + external_scroll_height;
|
||||||
this.el.css({
|
this.el.css({
|
||||||
height: container_height + 'px',
|
height: container_height + 'px',
|
||||||
|
|||||||
@@ -163,8 +163,16 @@ this repository contains the full copyright notices and license terms. -->
|
|||||||
applyThemeMode(
|
applyThemeMode(
|
||||||
document.documentElement.getAttribute('data-theme-mode'));
|
document.documentElement.getAttribute('data-theme-mode'));
|
||||||
jQuery('.body').show();
|
jQuery('.body').show();
|
||||||
|
function notifyLayoutResize() {
|
||||||
|
[0, 80, 180, 320].forEach(function(delay) {
|
||||||
|
window.setTimeout(function() {
|
||||||
|
window.dispatchEvent(new Event('resize'));
|
||||||
|
}, delay);
|
||||||
|
});
|
||||||
|
}
|
||||||
jQuery('[data-toggle="offcanvas"]').click(function() {
|
jQuery('[data-toggle="offcanvas"]').click(function() {
|
||||||
jQuery('.row-offcanvas').toggleClass('active');
|
jQuery('.row-offcanvas').toggleClass('active');
|
||||||
|
notifyLayoutResize();
|
||||||
});
|
});
|
||||||
jQuery('#tabs').on('ready', function() {
|
jQuery('#tabs').on('ready', function() {
|
||||||
var mq = window.matchMedia('(max-width: 991px)');
|
var mq = window.matchMedia('(max-width: 991px)');
|
||||||
|
|||||||
@@ -9685,6 +9685,48 @@ img.icon {
|
|||||||
.filter-box {
|
.filter-box {
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
}
|
}
|
||||||
|
.ag-grid-screen-filter-toggle-bar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
margin: 0 0 5px;
|
||||||
|
}
|
||||||
|
.ag-grid-tree-toolbar > .ag-grid-screen-filter-toggle-bar {
|
||||||
|
margin: 0 10px 0 auto;
|
||||||
|
}
|
||||||
|
.ag-grid-screen-filter-toggle {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 7px;
|
||||||
|
min-height: 30px;
|
||||||
|
padding: 4px 10px;
|
||||||
|
border: 1px solid #d6e4df;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: linear-gradient(180deg, #f6fbf9 0%, #edf5f1 100%);
|
||||||
|
color: #355154;
|
||||||
|
box-shadow: 0 2px 7px rgba(53, 81, 84, 0.1);
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.2;
|
||||||
|
text-transform: none !important;
|
||||||
|
transition: background-color 0.18s ease, border-color 0.18s ease,
|
||||||
|
box-shadow 0.18s ease, transform 0.18s ease;
|
||||||
|
}
|
||||||
|
.ag-grid-screen-filter-toggle:hover,
|
||||||
|
.ag-grid-screen-filter-toggle:focus {
|
||||||
|
background: linear-gradient(180deg, #f2faf7 0%, #e7f2ed 100%);
|
||||||
|
border-color: #bfd5cd;
|
||||||
|
color: #28484b;
|
||||||
|
box-shadow: 0 3px 9px rgba(53, 81, 84, 0.13);
|
||||||
|
}
|
||||||
|
.ag-grid-screen-filter-toggle:active {
|
||||||
|
transform: translateY(1px);
|
||||||
|
box-shadow: 0 1px 5px rgba(53, 81, 84, 0.1);
|
||||||
|
}
|
||||||
|
.ag-grid-screen-filter-toggle .icon {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
opacity: 0.78;
|
||||||
|
}
|
||||||
@media screen and (max-width: 991px) {
|
@media screen and (max-width: 991px) {
|
||||||
.filter-box button[disabled] {
|
.filter-box button[disabled] {
|
||||||
display: none;
|
display: none;
|
||||||
@@ -9696,6 +9738,13 @@ img.icon {
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
.content-box:not(.ag-grid-content-box) {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
height: auto;
|
||||||
|
min-height: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: visible;
|
||||||
|
}
|
||||||
.content-box.ag-grid-content-box {
|
.content-box.ag-grid-content-box {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
@@ -10788,10 +10837,10 @@ body {
|
|||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
.row-offcanvas:not(.active) .main-offcanvas {
|
.row-offcanvas:not(.active) .main-offcanvas {
|
||||||
float: none;
|
float: none !important;
|
||||||
flex: 0 0 100%;
|
flex: 0 0 100% !important;
|
||||||
width: 100%;
|
width: 100% !important;
|
||||||
max-width: 100%;
|
max-width: 100% !important;
|
||||||
}
|
}
|
||||||
.sidebar-offcanvas {
|
.sidebar-offcanvas {
|
||||||
position: absolute !important;
|
position: absolute !important;
|
||||||
|
|||||||
125
tryton-sao.js
125
tryton-sao.js
@@ -1278,6 +1278,11 @@ var Sao = {
|
|||||||
Mousetrap.bind(['ctrl+m', 'command+m'], function(e) {
|
Mousetrap.bind(['ctrl+m', 'command+m'], function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
jQuery('.row-offcanvas').toggleClass('active');
|
jQuery('.row-offcanvas').toggleClass('active');
|
||||||
|
[0, 80, 180, 320].forEach(function(delay) {
|
||||||
|
window.setTimeout(function() {
|
||||||
|
window.dispatchEvent(new Event('resize'));
|
||||||
|
}, delay);
|
||||||
|
});
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -12422,6 +12427,23 @@ var Sao = {
|
|||||||
'class': 'row'
|
'class': 'row'
|
||||||
}).appendTo(this.filter_box);
|
}).appendTo(this.filter_box);
|
||||||
this.el.append(this.filter_box);
|
this.el.append(this.filter_box);
|
||||||
|
this.ag_grid_filter_toggle_bar = jQuery('<div/>', {
|
||||||
|
'class': 'ag-grid-screen-filter-toggle-bar',
|
||||||
|
}).hide();
|
||||||
|
this.ag_grid_filter_toggle = jQuery('<button/>', {
|
||||||
|
'type': 'button',
|
||||||
|
'class': 'btn btn-default btn-sm ag-grid-screen-filter-toggle',
|
||||||
|
'aria-expanded': 'true',
|
||||||
|
'title': Sao.i18n.gettext('Hide filters'),
|
||||||
|
}).append(Sao.common.ICONFACTORY.get_icon_img('tryton-unfold-less', {
|
||||||
|
'aria-hidden': true,
|
||||||
|
})).append(jQuery('<span/>', {
|
||||||
|
'class': 'ag-grid-screen-filter-toggle-label',
|
||||||
|
'text': ' ' + Sao.i18n.gettext('Hide filters'),
|
||||||
|
})).appendTo(this.ag_grid_filter_toggle_bar);
|
||||||
|
this.ag_grid_filter_toggle.click(
|
||||||
|
this.toggle_ag_grid_filters.bind(this));
|
||||||
|
this.el.append(this.ag_grid_filter_toggle_bar);
|
||||||
this.filter_button = jQuery('<button/>', {
|
this.filter_button = jQuery('<button/>', {
|
||||||
type: 'button',
|
type: 'button',
|
||||||
'class': 'btn btn-link',
|
'class': 'btn btn-link',
|
||||||
@@ -12802,17 +12824,83 @@ var Sao = {
|
|||||||
this.tab.hide();
|
this.tab.hide();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
toggle_ag_grid_filters: function() {
|
||||||
|
this.set_ag_grid_filters_collapsed(
|
||||||
|
!this.el.hasClass('ag-grid-screen-filters-collapsed'));
|
||||||
|
},
|
||||||
|
set_ag_grid_filters_collapsed: function(collapsed) {
|
||||||
|
this.el.toggleClass('ag-grid-screen-filters-collapsed', collapsed);
|
||||||
|
if (collapsed) {
|
||||||
|
this.filter_box.hide();
|
||||||
|
} else {
|
||||||
|
this.filter_box.show();
|
||||||
|
}
|
||||||
|
if (this.ag_grid_filter_toggle) {
|
||||||
|
this.ag_grid_filter_toggle
|
||||||
|
.attr('aria-expanded', String(!collapsed))
|
||||||
|
.attr('title', Sao.i18n.gettext(
|
||||||
|
collapsed ? 'Show filters' : 'Hide filters'));
|
||||||
|
this.ag_grid_filter_toggle
|
||||||
|
.find('img.icon')
|
||||||
|
.replaceWith(Sao.common.ICONFACTORY.get_icon_img(
|
||||||
|
collapsed ? 'tryton-unfold-more' :
|
||||||
|
'tryton-unfold-less', {
|
||||||
|
'aria-hidden': true,
|
||||||
|
}));
|
||||||
|
this.ag_grid_filter_toggle
|
||||||
|
.find('.ag-grid-screen-filter-toggle-label')
|
||||||
|
.text(' ' + Sao.i18n.gettext(
|
||||||
|
collapsed ? 'Show filters' : 'Hide filters'));
|
||||||
|
}
|
||||||
|
window.setTimeout(() => {
|
||||||
|
window.dispatchEvent(new Event('resize'));
|
||||||
|
}, 0);
|
||||||
|
},
|
||||||
|
set_ag_grid_filter_toggle_visible: function(visible) {
|
||||||
|
if (!this.ag_grid_filter_toggle_bar) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.el.toggleClass('ag-grid-screen-with-filter-toggle', visible);
|
||||||
|
if (visible) {
|
||||||
|
this.ag_grid_filter_toggle_bar.show();
|
||||||
|
this.set_ag_grid_filters_collapsed(
|
||||||
|
this.el.hasClass('ag-grid-screen-filters-collapsed'));
|
||||||
|
} else {
|
||||||
|
this.ag_grid_filter_toggle_bar.hide();
|
||||||
|
this.el.removeClass('ag-grid-screen-filters-collapsed');
|
||||||
|
}
|
||||||
|
},
|
||||||
set: function(widget) {
|
set: function(widget) {
|
||||||
if (this.alternate_view) {
|
if (this.alternate_view) {
|
||||||
this.alternate_viewport.children().detach();
|
this.alternate_viewport.children().detach();
|
||||||
this.alternate_viewport.append(widget);
|
this.alternate_viewport.append(widget);
|
||||||
} else {
|
} else {
|
||||||
|
var is_ag_grid = Boolean(widget && widget.hasClass &&
|
||||||
|
widget.hasClass('ag-grid-tree-container'));
|
||||||
this.content_box.children().detach();
|
this.content_box.children().detach();
|
||||||
this.content_box.toggleClass(
|
this.content_box.toggleClass(
|
||||||
'ag-grid-content-box',
|
'ag-grid-content-box',
|
||||||
Boolean(widget && widget.hasClass &&
|
is_ag_grid);
|
||||||
widget.hasClass('ag-grid-tree-container')));
|
if (!is_ag_grid) {
|
||||||
|
this.content_box.css({
|
||||||
|
height: '',
|
||||||
|
minHeight: '',
|
||||||
|
flexBasis: '',
|
||||||
|
flexShrink: '',
|
||||||
|
width: '',
|
||||||
|
maxWidth: '',
|
||||||
|
});
|
||||||
|
}
|
||||||
this.content_box.append(widget);
|
this.content_box.append(widget);
|
||||||
|
if (is_ag_grid) {
|
||||||
|
var toolbar = widget.find('.ag-grid-tree-toolbar').first();
|
||||||
|
if (toolbar.length) {
|
||||||
|
toolbar.append(this.ag_grid_filter_toggle_bar);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.el.append(this.ag_grid_filter_toggle_bar);
|
||||||
|
}
|
||||||
|
this.set_ag_grid_filter_toggle_visible(is_ag_grid);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
get_text: function() {
|
get_text: function() {
|
||||||
@@ -26393,11 +26481,35 @@ function eval_pyson(value){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var rect = this.grid_host[0].getBoundingClientRect();
|
var rect = this.grid_host[0].getBoundingClientRect();
|
||||||
var available = window.innerHeight - rect.top - 36;
|
|
||||||
var height = Math.max(420, Math.min(720, available));
|
|
||||||
height = Math.max(520, height);
|
|
||||||
var content_box = this.grid_host.closest('.content-box.ag-grid-content-box');
|
var content_box = this.grid_host.closest('.content-box.ag-grid-content-box');
|
||||||
var screen_container = this.grid_host.closest('.screen-container');
|
var screen_container = this.grid_host.closest('.screen-container');
|
||||||
|
var toolbar_height = this.toolbar && this.toolbar.length ?
|
||||||
|
Math.ceil(this.toolbar.outerHeight(true)) : 0;
|
||||||
|
var external_scroll_height = 20;
|
||||||
|
var bottom_margin = 96;
|
||||||
|
var available = window.innerHeight - rect.top -
|
||||||
|
external_scroll_height - bottom_margin;
|
||||||
|
if (content_box.length) {
|
||||||
|
var content_rect = content_box[0].getBoundingClientRect();
|
||||||
|
available = Math.min(
|
||||||
|
available,
|
||||||
|
window.innerHeight - content_rect.top - toolbar_height -
|
||||||
|
external_scroll_height - bottom_margin);
|
||||||
|
}
|
||||||
|
var compact_min_height = 260;
|
||||||
|
var readable_min_height = 420;
|
||||||
|
var maximum_height = 720;
|
||||||
|
var height;
|
||||||
|
if (available >= compact_min_height) {
|
||||||
|
height = Math.max(
|
||||||
|
compact_min_height,
|
||||||
|
Math.min(maximum_height, available));
|
||||||
|
} else {
|
||||||
|
height = Math.max(
|
||||||
|
readable_min_height,
|
||||||
|
Math.min(maximum_height,
|
||||||
|
window.innerHeight - rect.top - bottom_margin));
|
||||||
|
}
|
||||||
var width_right = window.innerWidth - 12;
|
var width_right = window.innerWidth - 12;
|
||||||
if (screen_container.length) {
|
if (screen_container.length) {
|
||||||
width_right = Math.min(
|
width_right = Math.min(
|
||||||
@@ -26413,9 +26525,6 @@ function eval_pyson(value){
|
|||||||
width: available_width + 'px',
|
width: available_width + 'px',
|
||||||
maxWidth: available_width + 'px',
|
maxWidth: available_width + 'px',
|
||||||
});
|
});
|
||||||
var toolbar_height = this.toolbar && this.toolbar.length ?
|
|
||||||
Math.ceil(this.toolbar.outerHeight(true)) : 0;
|
|
||||||
var external_scroll_height = 20;
|
|
||||||
var container_height = height + toolbar_height + external_scroll_height;
|
var container_height = height + toolbar_height + external_scroll_height;
|
||||||
this.el.css({
|
this.el.css({
|
||||||
height: container_height + 'px',
|
height: container_height + 'px',
|
||||||
|
|||||||
Reference in New Issue
Block a user