changes
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
// = Form View Dark Mode
|
||||
// ============================================================================
|
||||
|
||||
.o_form_view {
|
||||
&:not(.o_field_highlight) .o_field_widget:not(.o_field_invalid):not(.o_field_highlight) .o_input:not(:hover):not(:focus) {
|
||||
--o-input-border-color: #{$o-gray-300};
|
||||
}
|
||||
&:not(.o_field_highlight) .o_required_modifier.o_field_widget:not(.o_field_invalid):not(.o_field_highlight) .o_input:not(:hover):not(:focus) {
|
||||
--o-input-border-color: #{$o-gray-400};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
.o_form_view {
|
||||
&:not(.o_field_highlight) .o_field_widget:not(.o_field_invalid):not(.o_field_highlight) .o_input:not(:hover):not(:focus) {
|
||||
--o-input-border-color: #{$gray-200};
|
||||
}
|
||||
&:not(.o_field_highlight) .o_required_modifier.o_field_widget:not(.o_field_invalid):not(.o_field_highlight) .o_input:not(:hover):not(:focus) {
|
||||
--o-input-border-color: #{$gray-400};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import { session } from '@web/session';
|
||||
import { patch } from '@web/core/utils/patch';
|
||||
import { append, createElement, setAttributes } from '@web/core/utils/xml';
|
||||
|
||||
import {FormCompiler} from '@web/views/form/form_compiler';
|
||||
|
||||
patch(FormCompiler.prototype, {
|
||||
compile(node, params) {
|
||||
const res = super.compile(node, params);
|
||||
const chatterContainerHookXml = res.querySelector(
|
||||
'.o_form_renderer > .o-mail-Form-chatter'
|
||||
);
|
||||
if (!chatterContainerHookXml) {
|
||||
return res;
|
||||
}
|
||||
setAttributes(chatterContainerHookXml, {
|
||||
't-ref': 'chatterContainer',
|
||||
});
|
||||
if (session.chatter_position === 'bottom') {
|
||||
const formSheetBgXml = res.querySelector('.o_form_sheet_bg');
|
||||
if (!chatterContainerHookXml || !formSheetBgXml?.parentNode) {
|
||||
return res;
|
||||
}
|
||||
const webClientViewAttachmentViewHookXml = res.querySelector(
|
||||
'.o_attachment_preview'
|
||||
);
|
||||
const chatterContainerXml = chatterContainerHookXml.querySelector(
|
||||
"t[t-component='__comp__.mailComponents.Chatter']"
|
||||
);
|
||||
const sheetBgChatterContainerHookXml = chatterContainerHookXml.cloneNode(true);
|
||||
const sheetBgChatterContainerXml = sheetBgChatterContainerHookXml.querySelector(
|
||||
"t[t-component='__comp__.mailComponents.Chatter']"
|
||||
);
|
||||
sheetBgChatterContainerHookXml.classList.add('o-isInFormSheetBg', 'w-auto');
|
||||
append(formSheetBgXml, sheetBgChatterContainerHookXml);
|
||||
setAttributes(sheetBgChatterContainerXml, {
|
||||
isInFormSheetBg: 'true',
|
||||
isChatterAside: 'false',
|
||||
});
|
||||
setAttributes(chatterContainerXml, {
|
||||
isInFormSheetBg: 'true',
|
||||
isChatterAside: 'false',
|
||||
});
|
||||
setAttributes(chatterContainerHookXml, {
|
||||
't-if': 'false',
|
||||
});
|
||||
if (webClientViewAttachmentViewHookXml) {
|
||||
setAttributes(webClientViewAttachmentViewHookXml, {
|
||||
't-if': 'false',
|
||||
});
|
||||
}
|
||||
} else {
|
||||
setAttributes(chatterContainerHookXml, {
|
||||
't-att-style': '__comp__.chatterState.width ? `width: ${__comp__.chatterState.width}px; max-width: ${__comp__.chatterState.width}px;` : ""',
|
||||
});
|
||||
const chatterContainerResizeHookXml = createElement('span');
|
||||
chatterContainerResizeHookXml.classList.add('o_fusion_chatter_handle');
|
||||
setAttributes(chatterContainerResizeHookXml, {
|
||||
't-on-mousedown.stop.prevent': '__comp__.onStartChatterResize.bind(__comp__)',
|
||||
't-on-dblclick.stop.prevent': '__comp__.onDoubleClickChatterResize.bind(__comp__)',
|
||||
});
|
||||
append(chatterContainerHookXml, chatterContainerResizeHookXml);
|
||||
}
|
||||
return res;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
import { useState, useRef } from '@odoo/owl';
|
||||
import { patch } from '@web/core/utils/patch';
|
||||
import { browser } from "@web/core/browser/browser";
|
||||
|
||||
import { FormRenderer } from '@web/views/form/form_renderer';
|
||||
|
||||
patch(FormRenderer.prototype, {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.chatterState = useState({
|
||||
width: browser.localStorage.getItem('fusion_backend_theme.width'),
|
||||
});
|
||||
this.chatterContainer = useRef('chatterContainer');
|
||||
},
|
||||
onStartChatterResize(ev) {
|
||||
if (ev.button !== 0) {
|
||||
return;
|
||||
}
|
||||
const initialX = ev.pageX;
|
||||
const chatterElement = this.chatterContainer.el;
|
||||
const initialWidth = chatterElement.offsetWidth;
|
||||
console.log("hi", ev, initialX, initialWidth)
|
||||
const resizeStoppingEvents = [
|
||||
'keydown', 'mousedown', 'mouseup'
|
||||
];
|
||||
const resizePanel = (ev) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
const newWidth = Math.min(
|
||||
Math.max(50, initialWidth - (ev.pageX - initialX)),
|
||||
Math.max(chatterElement.parentElement.offsetWidth - 250, 250)
|
||||
);
|
||||
browser.localStorage.setItem('fusion_backend_theme.width', newWidth);
|
||||
this.chatterState.width = newWidth;
|
||||
};
|
||||
const stopResize = (ev) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
if (ev.type === 'mousedown' && ev.button === 0) {
|
||||
return;
|
||||
}
|
||||
document.removeEventListener('mousemove', resizePanel, true);
|
||||
resizeStoppingEvents.forEach((stoppingEvent) => {
|
||||
document.removeEventListener(stoppingEvent, stopResize, true);
|
||||
});
|
||||
document.activeElement.blur();
|
||||
};
|
||||
document.addEventListener('mousemove', resizePanel, true);
|
||||
resizeStoppingEvents.forEach((stoppingEvent) => {
|
||||
document.addEventListener(stoppingEvent, stopResize, true);
|
||||
});
|
||||
},
|
||||
onDoubleClickChatterResize(ev) {
|
||||
browser.localStorage.removeItem('fusion_backend_theme.width');
|
||||
this.chatterState.width = false;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,99 @@
|
||||
import { useState, onWillStart, useEffect } from '@odoo/owl';
|
||||
|
||||
import { browser } from '@web/core/browser/browser';
|
||||
import { patch } from '@web/core/utils/patch';
|
||||
import { session } from '@web/session';
|
||||
|
||||
import {ControlPanel} from '@web/search/control_panel/control_panel';
|
||||
|
||||
patch(ControlPanel.prototype, {
|
||||
setup() {
|
||||
super.setup(...arguments);
|
||||
this.autoLoadState = useState({
|
||||
active: false,
|
||||
counter: 0,
|
||||
});
|
||||
onWillStart(() => {
|
||||
if (
|
||||
this.checkAutoLoadAvailability() &&
|
||||
this.getAutoLoadStorageValue()
|
||||
) {
|
||||
this.autoLoadState.active = true;
|
||||
}
|
||||
});
|
||||
useEffect(
|
||||
() => {
|
||||
if (!this.autoLoadState.active) {
|
||||
return;
|
||||
}
|
||||
this.autoLoadState.counter = (
|
||||
this.getAutoLoadRefreshInterval()
|
||||
);
|
||||
const interval = browser.setInterval(
|
||||
() => {
|
||||
this.autoLoadState.counter = (
|
||||
this.autoLoadState.counter ?
|
||||
this.autoLoadState.counter - 1 :
|
||||
this.getAutoLoadRefreshInterval()
|
||||
);
|
||||
if (this.autoLoadState.counter <= 0) {
|
||||
this.autoLoadState.counter = (
|
||||
this.getAutoLoadRefreshInterval()
|
||||
);
|
||||
if (this.pagerProps?.onUpdate) {
|
||||
this.pagerProps.onUpdate({
|
||||
offset: this.pagerProps.offset,
|
||||
limit: this.pagerProps.limit
|
||||
});
|
||||
} else if (typeof this.env.searchModel?.search) {
|
||||
this.env.searchModel.search();
|
||||
}
|
||||
}
|
||||
},
|
||||
1000
|
||||
);
|
||||
return () => browser.clearInterval(interval);
|
||||
},
|
||||
() => [this.autoLoadState.active]
|
||||
);
|
||||
},
|
||||
checkAutoLoadAvailability() {
|
||||
return ['kanban', 'list'].includes(this.env.config.viewType);
|
||||
},
|
||||
getAutoLoadRefreshInterval() {
|
||||
return (session.pager_autoload_interval ?? 30000) / 1000;
|
||||
},
|
||||
getAutoLoadStorageKey() {
|
||||
const keys = [
|
||||
this.env?.config?.actionId ?? '',
|
||||
this.env?.config?.viewType ?? '',
|
||||
this.env?.config?.viewId ?? '',
|
||||
];
|
||||
return `pager_autoload:${keys.join(',')}`;
|
||||
},
|
||||
getAutoLoadStorageValue() {
|
||||
return browser.localStorage.getItem(
|
||||
this.getAutoLoadStorageKey()
|
||||
);
|
||||
},
|
||||
setAutoLoadStorageValue() {
|
||||
browser.localStorage.setItem(
|
||||
this.getAutoLoadStorageKey(), true
|
||||
);
|
||||
},
|
||||
removeAutoLoadStorageValue() {
|
||||
browser.localStorage.removeItem(
|
||||
this.getAutoLoadStorageKey()
|
||||
);
|
||||
},
|
||||
toggleAutoLoad() {
|
||||
this.autoLoadState.active = (
|
||||
!this.autoLoadState.active
|
||||
);
|
||||
if (this.autoLoadState.active) {
|
||||
this.setAutoLoadStorageValue();
|
||||
} else {
|
||||
this.removeAutoLoadStorageValue();
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-inherit="web.ControlPanel" t-inherit-mode="extension">
|
||||
<xpath expr="//Pager/.." position="before">
|
||||
<div
|
||||
t-if="this.checkAutoLoadAvailability()"
|
||||
class="d-inline-flex align-items-center gap-1 align-self-center"
|
||||
>
|
||||
<span
|
||||
t-if="this.autoLoadState.active and this.autoLoadState.counter > 0"
|
||||
class="small text-muted"
|
||||
>
|
||||
<t t-out="this.autoLoadState.counter"/>s
|
||||
</span>
|
||||
<button
|
||||
t-if="!env.isSmall"
|
||||
class="btn btn-link p-0 d-inline-flex align-items-center justify-content-center"
|
||||
type="button"
|
||||
t-on-click.stop="this.toggleAutoLoad"
|
||||
>
|
||||
<i
|
||||
class="fa fa-refresh fa-fw"
|
||||
t-att-class="this.autoLoadState.active ? 'text-info fa-spin' : 'text-muted'"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
@@ -0,0 +1,45 @@
|
||||
import { Component } from '@odoo/owl';
|
||||
import { registry } from '@web/core/registry';
|
||||
import { DropdownItem } from '@web/core/dropdown/dropdown_item';
|
||||
|
||||
const cogMenuRegistry = registry.category('cogMenu');
|
||||
|
||||
export class CollapseAll extends Component {
|
||||
|
||||
static template = 'fusion_backend_theme.CollapseAll';
|
||||
static components = { DropdownItem };
|
||||
static props = {};
|
||||
|
||||
async onCollapseButtonClicked() {
|
||||
let groups = this.env.model.root.groups;
|
||||
while (groups.length) {
|
||||
const unfoldedGroups = groups.filter(
|
||||
(group) => !group._config.isFolded
|
||||
);
|
||||
if (unfoldedGroups.length) {
|
||||
for (const group of unfoldedGroups) {
|
||||
await group.toggle();
|
||||
}
|
||||
}
|
||||
const subGroups = unfoldedGroups.map(
|
||||
(group) => group.list.groups || []
|
||||
);
|
||||
groups = subGroups.reduce(
|
||||
(a, b) => a.concat(b), []
|
||||
);
|
||||
}
|
||||
await this.env.model.root.load();
|
||||
this.env.model.notify();
|
||||
}
|
||||
}
|
||||
|
||||
export const collapseAllItem = {
|
||||
Component: CollapseAll,
|
||||
groupNumber: 15,
|
||||
isDisplayed: async (env) => (
|
||||
['kanban', 'list'].includes(env.config.viewType) &&
|
||||
env.model.root.isGrouped
|
||||
)
|
||||
};
|
||||
|
||||
cogMenuRegistry.add('collapse-all-menu', collapseAllItem, { sequence: 2 });
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="fusion_backend_theme.CollapseGroups">
|
||||
<DropdownItem
|
||||
class="'o_fusion_collapse_groups'"
|
||||
onSelected.bind="onCollapseButtonClicked"
|
||||
>
|
||||
<i class="fa fa-fw fa-compress me-1"/>Collapse All
|
||||
</DropdownItem>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
@@ -0,0 +1,45 @@
|
||||
import { Component } from '@odoo/owl';
|
||||
import { registry } from '@web/core/registry';
|
||||
import { DropdownItem } from '@web/core/dropdown/dropdown_item';
|
||||
|
||||
const cogMenuRegistry = registry.category('cogMenu');
|
||||
|
||||
export class ExpandAll extends Component {
|
||||
|
||||
static template = 'fusion_backend_theme.ExpandAll';
|
||||
static components = { DropdownItem };
|
||||
static props = {};
|
||||
|
||||
async onExpandButtonClicked() {
|
||||
let groups = this.env.model.root.groups;
|
||||
while (groups.length) {
|
||||
const foldedGroups = groups.filter(
|
||||
(group) => group._config.isFolded
|
||||
);
|
||||
if (foldedGroups.length) {
|
||||
for (const group of foldedGroups) {
|
||||
await group.toggle();
|
||||
}
|
||||
}
|
||||
const subGroups = foldedGroups.map(
|
||||
(group) => group.list.groups || []
|
||||
);
|
||||
groups = subGroups.reduce(
|
||||
(a, b) => a.concat(b), []
|
||||
);
|
||||
}
|
||||
await this.env.model.root.load();
|
||||
this.env.model.notify();
|
||||
}
|
||||
}
|
||||
|
||||
export const expandAllItem = {
|
||||
Component: ExpandAll,
|
||||
groupNumber: 15,
|
||||
isDisplayed: async (env) => (
|
||||
['kanban', 'list'].includes(env.config.viewType) &&
|
||||
env.model.root.isGrouped
|
||||
)
|
||||
};
|
||||
|
||||
cogMenuRegistry.add('expand-all-menu', expandAllItem, { sequence: 1 });
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="fusion_backend_theme.ExpandGroups">
|
||||
<DropdownItem
|
||||
class="'o_fusion_expand_groups'"
|
||||
onSelected.bind="onExpandButtonClicked"
|
||||
>
|
||||
<i class="fa fa-fw fa-expand me-1"/>Expand All
|
||||
</DropdownItem>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
Reference in New Issue
Block a user