[init/add] generic backend theme
BIN
muk_web_theme-19/muk_web_refresh/static/description/banner.png
Normal file
|
After Width: | Height: | Size: 125 KiB |
|
After Width: | Height: | Size: 364 KiB |
BIN
muk_web_theme-19/muk_web_refresh/static/description/icon.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
@@ -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_TzoLSQBFjHhkFKLgpM6wqrWXRbeXQKzS"><rect width="100" height="100"/></clipPath></defs><g clip-path="url(#_clipPath_TzoLSQBFjHhkFKLgpM6wqrWXRbeXQKzS)"><rect width="100" height="100" style="fill:rgb(0,0,0)" fill-opacity="0"/><path d=" M 93.77 37.5 L 95.313 37.5 C 97.91 37.5 100 35.411 100 32.813 L 100 4.689 C 100 2.794 98.867 1.076 97.109 0.353 C 95.352 -0.37 93.34 0.041 91.992 1.369 L 81.895 11.486 C 73.243 4.318 62.111 0.001 50.001 0.001 C 24.807 0.001 3.968 18.634 0.511 42.871 C 0.023 46.289 2.386 49.453 5.804 49.941 C 9.221 50.43 12.385 48.047 12.874 44.649 C 15.471 26.466 31.115 12.501 50.001 12.501 C 58.673 12.501 66.642 15.431 72.989 20.372 L 63.868 29.493 C 62.521 30.84 62.13 32.852 62.853 34.61 C 63.575 36.368 65.294 37.5 67.188 37.5 L 93.77 37.5 Z " fill="rgb(150,43,72)"/><path d=" M 99.512 57.129 C 100 53.711 97.617 50.547 94.219 50.059 C 90.821 49.57 87.637 51.953 87.149 55.351 C 84.551 73.515 68.907 87.479 50.021 87.479 C 41.349 87.479 33.381 84.55 27.033 79.608 L 36.135 70.507 C 37.482 69.16 37.873 67.148 37.15 65.39 C 36.428 63.632 34.709 62.5 32.815 62.5 L 4.69 62.5 C 2.093 62.5 0.003 64.589 0.003 67.187 L 0.003 95.311 C 0.003 97.206 1.136 98.924 2.894 99.647 C 4.651 100.37 6.663 99.959 8.011 98.631 L 18.127 88.514 C 26.76 95.682 37.892 99.999 50.001 99.999 C 75.196 99.999 96.035 81.366 99.492 57.129 L 99.512 57.129 Z " fill="rgb(252,134,139)"/></g></svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
137
muk_web_theme-19/muk_web_refresh/static/description/index.html
Normal file
@@ -0,0 +1,137 @@
|
||||
<section class="oe_container">
|
||||
<div class="oe_row oe_spaced">
|
||||
<h2 class="oe_slogan">MuK Web Refresh</h2>
|
||||
<h3 class="oe_slogan mb-0">Automatically refresh any list or kanban view</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">
|
||||
Activate the auto-refresh button to reload the view every 30 seconds.
|
||||
The refresh will reload and update the view’s data. The refresh button
|
||||
is visible in every list and kanban view, on the left side of the pager.
|
||||
</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>
|
||||
BIN
muk_web_theme-19/muk_web_refresh/static/description/logo.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 581 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 24 KiB |
@@ -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,39 @@
|
||||
import { expect, test } from '@odoo/hoot';
|
||||
import {
|
||||
models,
|
||||
fields,
|
||||
defineModels,
|
||||
mountView,
|
||||
onRpc,
|
||||
contains,
|
||||
} from '@web/../tests/web_test_helpers';
|
||||
|
||||
class Product extends models.Model {
|
||||
name = fields.Char();
|
||||
_records = [
|
||||
{ id: 1, name: 'Test 1' },
|
||||
{ id: 2, name: 'Test 2' },
|
||||
];
|
||||
}
|
||||
defineModels({ Product });
|
||||
|
||||
onRpc('has_group', () => true);
|
||||
|
||||
test(
|
||||
'refresh toggle switches active state',
|
||||
async () => {
|
||||
await mountView({
|
||||
type: 'list',
|
||||
resModel: 'product',
|
||||
arch: `<list><field name='name'/></list>`,
|
||||
});
|
||||
expect('.o_control_panel i.fa-refresh').toHaveClass('text-muted');
|
||||
expect('.o_control_panel i.fa-refresh').not.toHaveClass('fa-spin');
|
||||
await contains('.o_control_panel i.fa-refresh').click();
|
||||
expect('.o_control_panel i.fa-refresh').toHaveClass('fa-spin');
|
||||
expect('.o_control_panel i.fa-refresh').toHaveClass('text-info');
|
||||
expect('.o_control_panel i.fa-refresh').not.toHaveClass('text-muted');
|
||||
await contains('.o_control_panel i.fa-refresh').click();
|
||||
expect('.o_control_panel i.fa-refresh').not.toHaveClass('fa-spin');
|
||||
expect('.o_control_panel i.fa-refresh').toHaveClass('text-muted');
|
||||
});
|
||||