[init/add] generic backend theme

This commit is contained in:
Daveanand Mannie
2026-01-09 20:25:07 -05:00
commit 8af4c7e966
213 changed files with 6068 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 365 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="isolation:isolate" viewBox="0 0 100 100" width="100pt" height="100pt"><defs><clipPath id="_clipPath_Yuq418q6kkRpC6ptYTVECmDFl5mRFiaT"><rect width="100" height="100"/></clipPath></defs><g clip-path="url(#_clipPath_Yuq418q6kkRpC6ptYTVECmDFl5mRFiaT)"><rect width="100" height="100" style="fill:rgb(0,0,0)" fill-opacity="0"/><clipPath id="_clipPath_ygSdMlYGWMy0MjXG6IaCHRxLKezsxlsO"><rect x="0" y="0" width="100" height="100" transform="matrix(1,0,0,1,0,0)" fill="rgb(255,255,255)"/></clipPath><g clip-path="url(#_clipPath_ygSdMlYGWMy0MjXG6IaCHRxLKezsxlsO)"><g><rect x="0" y="0" width="100" height="100" transform="matrix(1,0,0,1,0,0)" fill="none"/><path d=" M 64.989 0 L 94.987 0 C 97.758 0 99.987 2.229 99.987 5 L 99.987 34.998 C 99.987 37.019 98.779 38.852 96.904 39.623 C 95.029 40.394 92.883 39.977 91.446 38.54 L 83.321 30.415 L 65.197 48.539 C 63.239 50.497 60.072 50.497 58.135 48.539 L 51.469 41.873 C 49.51 39.915 49.51 36.748 51.469 34.811 L 69.593 16.687 L 61.447 8.541 C 60.01 7.104 59.593 4.958 60.364 3.083 C 61.135 1.208 62.968 0 64.989 0 Z " fill="rgb(152,81,132)"/><path d=" M 35.003 100 L 4.989 100 C 2.217 100 -0.013 97.77 -0.013 94.998 L -0.013 64.984 C -0.013 62.962 1.196 61.128 3.072 60.356 C 4.948 59.585 7.094 60.002 8.533 61.44 L 16.661 69.569 L 34.795 51.436 C 36.754 49.476 39.922 49.476 41.861 51.436 L 48.531 58.105 C 50.49 60.065 50.49 63.233 48.531 65.171 L 30.397 83.305 L 38.526 91.433 C 39.964 92.872 40.381 95.018 39.61 96.894 C 38.839 98.77 37.004 99.979 34.983 99.979 L 35.003 100 Z " fill="rgb(251,185,69)"/></g></g></g></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -0,0 +1,139 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan">MuK Groups</h2>
<h3 class="oe_slogan mb-0">Adds expand/collapse for views</h3>
<img src="logo.png" style="width: 150px;" class="mx-auto center-block">
<h4 class="oe_slogan mt-0" style="font-size: 23px">MuK IT GmbH - www.mukit.at</h4>
<div class="mb-4" style="text-align: center;">
<span
class="btn btn-sm mb-2"
style="font-size:14px; font-weight:500; background-color:#243742; color:#fff; cursor:default;"
>
<i class="fa fa-check"></i> Community
</span>
<span
class="btn btn-sm mb-2"
style="font-size:14px; font-weight:500; background-color:#5D8DA8; color:#fff; cursor:default;"
>
<i class="fa fa-check me-1"></i> Enterprise
</span>
</div>
<div class="oe_demo oe_screenshot"
style="max-width: 84%; margin: 16px 8%">
<img src="screenshot.png">
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="text-justify" style="max-width: 84%; margin: 16px 8%;">
<h3 class="oe_slogan">Overview</h3>
<p class="oe_mt32">
The extension adds one-click controls to expand or collapse all groups in
backend list and kanban views. When a view is grouped by any field, two new
actions <em>Expand All</em> and <em>Collapse All</em>em> appear in the cog
menu, making it faster to expand large datasets or hide detail when you only
need a summary.
</p>
</div>
</div>
</section>
<section
class="oe_container oe_dark d-flex justify-content-around align-items-lg-center flex-column flex-lg-row">
<div class="d-flex flex-column m-3 ms-lg-4">
<h3 class="oe_slogan mb-3 mt-3 text-left">
<i class="fa fa-comments mr8"></i>Want more?
</h3>
<p>
Are you having troubles with your Odoo integration? Or do you feel
your system lacks of essential features? <br>If your answer is <b>YES</b>
to one of the above questions, feel free to contact us at anytime
with your inquiry. <br>We are looking forward to discuss your
needs and plan the next steps with you. <br>
</p>
</div>
<div
class="oe_slogan d-flex flex-column ms-1 me-1 ms-lg-4 me-lg-4 flex-grow-1">
<a class="btn btn-primary btn-lg m-3"
href="mailto:sale@mukit.at?subject=Request%20Quote"
style="font-size: 1.2rem; position: relative; overflow: hidden;">
<i class="fa fa-envelope me-1"></i>REQUEST QUOTE
</a>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<h3 class="oe_slogan">Our Services</h3>
<div class="d-flex justify-content-between">
<div>
<div>
<div style="width: 75px; height: 75px; border-radius: 100%; margin: auto">
<img src="/service_development.png" style="width: 100%; border-radius: 100%">
</div>
<h3
class="oe_slogan"
style="text-align: center; font-size: 14px; width: 100%; margin: 0; margin-top: 5px; color: #000 !important; opacity: 1 !important; line-height: 17px"
>
Odoo <br>Development
</h3>
</div>
</div>
<div>
<div>
<div style="width: 75px; height: 75px; border-radius: 100%; margin: auto">
<img src="/service_integration.png" style="width: 100%; border-radius: 100%">
</div>
<h3
class="oe_slogan"
style="text-align: center; font-size: 14px; width: 100%; margin: 0; margin-top: 5px; color: #000 !important; opacity: 1 !important; line-height: 17px"
>
Odoo <br>Integration
</h3>
</div>
</div>
<div>
<div>
<div style="width: 75px; height: 75px; border-radius: 100%; margin: auto">
<img src="/service_infrastructure.png" style="width: 100%; border-radius: 100%">
</div>
<h3
class="oe_slogan"
style="text-align: center; font-size: 14px; width: 100%; margin: 0; margin-top: 5px; color: #000 !important; opacity: 1 !important; line-height: 17px"
>
Odoo <br>Infrastructure
</h3>
</div>
</div>
<div>
<div>
<div style="width: 75px; height: 75px; border-radius: 100%; margin: auto">
<img src="/service_training.png" style="width: 100%; border-radius: 100%">
</div>
<h3
class="oe_slogan"
style="text-align: center; font-size: 14px; width: 100%; margin: 0; margin-top: 5px; color: #000 !important; opacity: 1 !important; line-height: 17px"
>
Odoo <br>Training
</h3>
</div>
</div>
<div>
<div>
<div style="width: 75px; height: 75px; border-radius: 100%; margin: auto">
<img src="/service_support.png" style="width: 100%; border-radius: 100%">
</div>
<h3
class="oe_slogan"
style="text-align: center; font-size: 14px; width: 100%; margin: 0; margin-top: 5px; color: #000 !important; opacity: 1 !important; line-height: 17px"
>
Odoo <br>Support
</h3>
</div>
</div>
</div>
</div>
</section>

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -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 = 'muk_web_group.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 });

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="muk_web_group.CollapseAll">
<DropdownItem
class="'mk_collapse_all_menu'"
onSelected.bind="onCollapseButtonClicked"
>
<i class="fa fa-fw fa-compress me-1"/>Collapse All
</DropdownItem>
</t>
</templates>

View File

@@ -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 = 'muk_web_group.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 });

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="muk_web_group.ExpandAll">
<DropdownItem
class="'mk_expand_all_menu'"
onSelected.bind="onExpandButtonClicked"
>
<i class="fa fa-fw fa-expand me-1"/>Expand All
</DropdownItem>
</t>
</templates>

View File

@@ -0,0 +1,52 @@
import { expect, test } from '@odoo/hoot';
import {
models,
fields,
defineModels,
mountView,
contains,
onRpc,
} from '@web/../tests/web_test_helpers';
class Category extends models.Model {
name = fields.Char();
_records = [
{ id: 1, name: 'Cat A' },
{ id: 2, name: 'Cat B' },
];
}
class Product extends models.Model {
name = fields.Char();
category_id = fields.Many2one({
relation: 'category',
});
_records = [
{ id: 1, name: 'A-1', category_id: 1 },
{ id: 2, name: 'A-2', category_id: 1 },
{ id: 3, name: 'B-1', category_id: 2 },
];
}
defineModels({ Category, Product });
onRpc('has_group', () => true);
test('expand/collapse all groups from cog menu in grouped list', async () => {
await mountView({
type: 'list',
resModel: 'product',
groupBy: ['category_id'],
arch: `<list string='Products'><field name='name'/><field name='category_id'/></list>`,
});
expect('.o_group_header').toHaveCount(2);
await contains('.o_cp_action_menus .dropdown-toggle').click();
expect('.mk_expand_all_menu').toHaveCount(1);
expect('.mk_collapse_all_menu').toHaveCount(1);
await contains('.mk_expand_all_menu').click();
expect('tbody tr.o_data_row').toHaveCount(3);
await contains('.o_cp_action_menus .dropdown-toggle').click();
await contains('.mk_collapse_all_menu').click();
expect('tbody tr.o_data_row').toHaveCount(0);
expect('.o_group_header').toHaveCount(2);
});