[IMP] web, base: adapt for dark-mode

This commit adapts several components in order to correctly handle
color-scheme variations.

It also allows user_menu to handle switch entries 

task-2710677

Part-of: odoo/odoo#102868
This commit is contained in:
stefanorigano (SRI)
2022-10-11 13:15:53 +02:00
committed by Pierre Paridans
parent 1ced9f10aa
commit 5234fad374
58 changed files with 369 additions and 182 deletions
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="621px" height="196px" viewBox="0 0 621 196" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Odoo Logo</title>
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="odoo_logo" fill-rule="nonzero">
<path d="M546,196 C504.579,196 471,162.421 471,121 C471,79.579 504.579,46 546,46 C587.421,46 621,79.579 621,121 C621,162.421 587.421,196 546,196 Z M546,165 C570.3,165 590,145.3 590,121 C590,96.7 570.3,77 546,77 C521.7,77 502,96.7 502,121 C502,145.3 521.7,165 546,165 Z M389,196 C347.579,196 314,162.421 314,121 C314,79.579 347.579,46 389,46 C430.421,46 464,79.579 464,121 C464,162.421 430.421,196 389,196 Z M389,165 C413.3,165 433,145.3 433,121 C433,96.7 413.3,77 389,77 C364.7,77 345,96.7 345,121 C345,145.3 364.7,165 389,165 Z M307,120 C307,161.935 273.408,196 231.991,196 C190.575,196 157,162.005 157,120.07 C157,78.134 187.5,46 231.991,46 C248.433,46 263.638,49.496 275.998,58.58 L276,15.09 C276,6.756 283.27,0 291.5,0 C299.728,0 307,6.762 307,15.09 L307,120 Z M232,165 C256.3,165 276,145.3 276,121 C276,96.7 256.3,77 232,77 C207.7,77 188,96.7 188,121 C188,145.3 207.7,165 232,165 Z" fill="#FFFFFF"></path>
<path d="M75,196 C33.579,196 0,162.421 0,121 C0,79.579 33.579,46 75,46 C116.421,46 150,79.579 150,121 C150,162.421 116.421,196 75,196 Z M75,165 C99.3,165 119,145.3 119,121 C119,96.7 99.3,77 75,77 C50.7,77 31,96.7 31,121 C31,145.3 50.7,165 75,165 Z" fill="#FFFFFF"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

@@ -1,14 +1,14 @@
$bs-datetimepicker-timepicker-font-size: 1.2em !default;
$bs-datetimepicker-active-bg: $blue !default;
$bs-datetimepicker-active-color: $white !default;
$bs-datetimepicker-border-radius: $border-radius !default;
$bs-datetimepicker-btn-hover-bg: $gray-200 !default;
$bs-datetimepicker-disabled-color: $gray-600 !default;
$bs-datetimepicker-alternate-color: $gray-600 !default;
$bs-datetimepicker-secondary-border-color: #ccc !default;
$bs-datetimepicker-secondary-border-color-rgba: rgba(0, 0, 0, 0.2) !default;
$bs-datetimepicker-primary-border-color: white !default;
$bs-datetimepicker-text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25) !default;
$bs-datetimepicker-timepicker-font-size: var(--bs-datetimepicker-timepicker-font-size, 1.2em) !default;
$bs-datetimepicker-active-bg: var(--bs-datetimepicker-active-bg, #{$blue}) !default;
$bs-datetimepicker-active-color: var(--bs-datetimepicker-active-color, #{$white}) !default;
$bs-datetimepicker-border-radius: var(--bs-datetimepicker-border-radius, #{$border-radius}) !default;
$bs-datetimepicker-btn-hover-bg: var(--bs-datetimepicker-btn-hover-bg, #{$gray-200}) !default;
$bs-datetimepicker-disabled-color: var(--bs-datetimepicker-disabled-color, #{$gray-600}) !default;
$bs-datetimepicker-alternate-color: var(--bs-datetimepicker-alternate-color, #{$gray-600}) !default;
$bs-datetimepicker-secondary-border-color: var(--bs-datetimepicker-secondary-border-color, #ccc) !default;
$bs-datetimepicker-secondary-border-color-rgba: var(--bs-datetimepicker-secondary-border-color-rgba, rgba(0, 0, 0, 0.2)) !default;
$bs-datetimepicker-primary-border-color: var(--bs-datetimepicker-primary-border-color, white) !default;
$bs-datetimepicker-text-shadow: var(--bs-datetimepicker-text-shadow, 0 -1px 0 rgba(0, 0, 0, 0.25)) !default;
.bootstrap-datetimepicker-widget {
list-style: none;
@@ -1,7 +1,7 @@
.o_colorlist {
button {
border: 1px solid white;
box-shadow: 0 0 0 1px #c9ccd2;
border: 1px solid $white;
box-shadow: 0 0 0 1px $gray-500;
width: 22px;
height: 17px;
}
@@ -58,7 +58,7 @@
<button class="btn btn-link" t-on-click="() => { state.showTraceback = !state.showTraceback }">See details</button>
<div t-if="state.showTraceback and (props.name or props.message)" class="alert clearfix" style="background-color:#ececec;" role="alert">
<div t-if="state.showTraceback and (props.name or props.message)" class="alert alert-info bg-100 clearfix" role="alert">
<code t-if="props.name" t-esc="props.name"></code>
<p t-if="props.message" t-esc="props.message"></p>
</div>
@@ -19,7 +19,7 @@ odoo.define('web.basic_fields_owl', function (require) {
*/
class FieldBadge extends AbstractField {
_getClassFromDecoration(decoration) {
return `bg-${decoration.split('-')[1]}`;
return `text-bg-${decoration.split('-')[1]}`;
}
}
FieldBadge.description = _lt("Badge");
@@ -49,13 +49,16 @@ div.dropdown-menu.bootstrap-datetimepicker-widget {
}
.bootstrap-datetimepicker-widget .datepicker table {
--datepicker-color: #{map-get($grays, '900')};
--datepicker__thead-bg: #{map-get($grays, '100')};
th, td {
border-radius: 0;
border-bottom-width: $border-width;
width: percentage(1/8);
height: 30px;
line-height: 30px;
color: map-get($grays, '900');
color: var(--datepicker-color);
&.prev, &.next, &.old, &.new {
@include o-hover-opacity(.5);
@@ -72,7 +75,7 @@ div.dropdown-menu.bootstrap-datetimepicker-widget {
}
thead tr:nth-child(2) th, td.cw {
background-color: map-get($grays, '100');
background-color: var(--datepicker__thead-bg);
font-size: $font-size-sm;
font-weight: $font-weight-bold;
color: $o-main-text-color;
@@ -102,8 +105,8 @@ div.dropdown-menu.bootstrap-datetimepicker-widget {
margin: 0;
border-radius: 0;
color: $o-main-text-color;
border-top: 1px solid $border-color;
box-shadow: 0 1px 0 $border-color; // overlaps with main box border
border-top: 1px solid var(--datepicker-border-color, #{$border-color});
box-shadow: 0 1px 0 var(--datepicker-border-color, #{$border-color}); // overlaps with main box border
&.primary {
color: $o-brand-primary;
@@ -1,19 +1,63 @@
// Match DateTimePicker styling
.daterangepicker {
.daterangepicker.show-calendar {
--daterangepicker-border: #{$dropdown-border-width} solid #{$dropdown-border-color};
--daterangepicker-border-radius: #{$dropdown-border-radius};
--daterangepicker-bg: #{$dropdown-bg};
--daterangepicker-color: #{map-get($grays, '900')};
@if $enable-shadows {
--daterangepicker-box-shadow: #{$dropdown-box-shadow};
}
--daterangepicker__table-bg: #{$table-bg};
--daterangepicker__thead-bg: #{map-get($grays, '100')};
--daterangepicker__cell-border-color: #{$table-border-color};
--daterangepicker__cell-bg--hover: #{map-get($grays, '100')};
--daterangepicker__select-bg: #{$form-select-bg};
--daterangepicker__select-border-color: #{$input-border-color};
--daterangepicker__select-color: #{$form-select-color};
border: var(--daterangepicker-border);
border-radius: var(--daterangepicker-border-radius);
background-color: var(--daterangepicker-bg);
box-shadow: var(--daterangepicker-box-shadow);
font-family: inherit;
&:before {
border-bottom-color: var(--daterangerpicker__arrow-border-color, #{$dropdown-border-color});
}
&:after {
border-bottom-color: var(--daterangerpicker__arrow-background-color, #{$dropdown-bg});
}
.calendar-table {
border: 0;
background-color: var(--daterangepicker__table-bg);
.next span, .prev span {
border-color: currentColor;
}
td, th {
border-bottom-color: $table-border-color;
border-bottom-color: var(--daterangepicker__cell-border-color);
&, &.start-date.end-date {
border-radius: 0;
}
&:not(.active) {
color: map-get($grays, '900');
color: var(--daterangepicker-color);
}
&.available:hover {
background-color: var(--daterangepicker__cell-bg--hover);
}
&.prev, &.next, &.off.ends {
@include o-hover-opacity(.5);
@@ -46,11 +90,17 @@
}
&.active,
&.active:hover {
&.active:hover,
&.in-range:hover {
background-color: $o-brand-odoo;
color: $white;
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
}
&.off {
background-color: transparent;
}
}
thead tr {
@@ -63,7 +113,7 @@
}
}
&:nth-child(2) th {
background-color: map-get($grays, '100');
background-color: var(--daterangepicker__thead-bg);
font-size: $font-size-sm;
font-weight: $font-weight-bold;
color: $o-main-text-color;
@@ -74,14 +124,26 @@
.calendar-time select {
&.hourselect, &.minuteselect, &.secondselect, &.ampmselect {
display: initial;
border-color: var(--daterangepicker__select-border-color);
background-color: var(--daterangepicker__select-bg);
color: var(--daterangepicker__select-color);
-webkit-appearance: menulist-button;
-moz-appearance: menulist-button;
appearance: menulist-button;
}
}
.drp-buttons .drp-selected {
display: none;
.drp-buttons {
border-top: 0;
.btn {
text-transform: uppercase;
font-weight: $btn-font-weight;
}
.drp-selected {
display: none;
}
}
@include media-breakpoint-down(sm) {
@@ -69,7 +69,7 @@
display: block;
margin-top: 16px;
padding: 8px 10px 12px;
background: map-get($grays, '900');
background: var(--DomainDebugContainer-background-colomap-get, #{$o-gray-900});
color: rgba(white, 0.5);
font-family: monospace;
font-weight: normal;
@@ -3,13 +3,23 @@
.ui-widget.ui-autocomplete {
top: 0; // Compute initial position
min-width: 0; // Compute initial width
color: $dropdown-color;
// Needed because .ui-widget are rendered at a
// lower stacking contex compared to modals.
z-index: $zindex-modal + 1;
&.ui-widget-content {
background-color: $dropdown-bg;
border: $dropdown-border-width solid $dropdown-border-color;
@include border-radius($dropdown-border-radius);
@include box-shadow($dropdown-box-shadow);
}
.ui-menu-item {
> a {
@include o-hover-text-color($dropdown-link-color, $dropdown-link-hover-color);
&.dropdown-item {
padding: $o-dropdown-vpadding $o-dropdown-hpadding;
}
@@ -163,7 +163,8 @@
}
.o_m2o_avatar_empty {
display: block;
background-color: #e9ecef;
background: $o-black;
opacity: .1;
}
}
@@ -407,7 +407,7 @@
}
.oe_kanban_text_red {
color: #A61300;
color: o-text-color('danger');
font-weight: $font-weight-bold;
}
@@ -274,7 +274,7 @@
.o_data_row.o_selected_row > .o_data_cell:not(.o_readonly_modifier):not(.o_invisible_modifier) {
position: relative; // for o_field_translate
&:not(.o_handle_cell) {
background-color: white;
background-color: $o-view-background-color;
}
.o_input {
border: none;
+3 -2
View File
@@ -86,9 +86,10 @@
border: none;
.modal-header {
background: $o-brand-odoo;
background: $o-navbar-background;
.modal-title, .o_subtitle, button.close {
color: white;
color: $o-navbar-entry-color;
}
}
@@ -3,6 +3,10 @@
position: relative;
}
.o_web_sign_signature_group {
background: #ffffff;
}
/* Signature Dialog */
// The .card selector is important to make sure the position absolute will take
// priority over the position relative of the card.
@@ -57,7 +57,6 @@
position: fixed;
z-index: 1060;
border: 1px solid $border-color;
background-color: #fff;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
.o_popover_header {
@@ -14,10 +14,10 @@
height: 15px;
vertical-align: middle;
border: 1px solid lighten($o-brand-secondary, 25%);
border: 1px solid $o-gray-300;
overflow: hidden;
background-color: white;
background-color: $o-view-background-color;
&.o_progress_overflow {
background-color: $o-brand-secondary;
}
@@ -3,7 +3,6 @@ $bs-datetimepicker-active-bg: $o-brand-odoo;
$bs-datetimepicker-active-color: $white;
$bs-datetimepicker-text-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
$bs-datetimepicker-secondary-border-color: $dropdown-border-color;
$bs-datetimepicker-secondary-border-color-rgba: $dropdown-border-color;
// TODO remove sr-only when TempusDominus is upgraded to 6+
.sr-only {
+1 -1
View File
@@ -312,7 +312,7 @@
}
@mixin o-kanban-dropdown-open {
position: relative;
background: white;
background: $dropdown-bg;
border-color: $border-color;
z-index: $zindex-dropdown + 1;
}
+7 -3
View File
@@ -50,9 +50,13 @@
// No content helper
.o_view_nocontent {
@include o-position-absolute(30%, 0, 0, 0);
@include o-position-absolute(0, 0, 0, 0);
pointer-events: none;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
background-image: radial-gradient(at 50% 50%, #{$o-view-background-color} 0px, #{rgba($o-view-background-color, 0.5)} 100%);
.o_nocontent_help {
@include o-nocontent-empty;
@@ -100,8 +104,8 @@
.o_nocontent_help {
border-radius: 20%;
background-color: #f9f9f9;
box-shadow: 0 0 120px 100px #f9f9f9;
background-color: $o-view-background-color;
box-shadow: 0 0 120px 100px $o-view-background-color;
}
.o_sample_data_disabled {
+1 -1
View File
@@ -1016,7 +1016,7 @@
<div t-if="widget.mode === 'edit'" class="o_field_widget o_field_many2one" aria-atomic="true">
<div class="o_field_many2one_selection">
<div class="o_input_dropdown">
<input type="text" class="o_input"
<input type="text" class="o_input form-control"
t-att-barcode_events="widget.nodeOptions.barcode_events"
t-att-tabindex="widget.attrs.tabindex"
t-att-autofocus="widget.attrs.autofocus"
@@ -49,7 +49,7 @@
border, but we remove the padding from the body, so the canvas
will overflow on the corners without this rule.
-->
<div class="o_web_sign_signature_group bg-white card mt-3" style="overflow: hidden;">
<div class="o_web_sign_signature_group position-relative mt-3 border" style="overflow: hidden;">
<div class="card-header">
<div class="row g-0">
<div class="col-auto">
+5 -3
View File
@@ -15,7 +15,7 @@ $cyan: #17a2b8 !default;
//End Restore BS4 Colors
// All of those are BS default
$white: #fff !default;
$white: $o-white !default;
$gray-100: $o-gray-100 !default;
$gray-200: $o-gray-200 !default;
$gray-300: $o-gray-300 !default;
@@ -26,7 +26,7 @@ $gray-700: $o-gray-700 !default;
$gray-800: $o-gray-800 !default;
$gray-900: $o-gray-900 !default;
$black: #000 !default;
$black: $o-black !default;
$primary: $o-brand-primary !default;
$secondary: $white !default;
@@ -70,7 +70,7 @@ $spacer: 1rem !default;
//
// Settings for the `<body>` element.
$body-bg: $o-main-bg-color !default;
$body-bg: $o-webclient-background-color !default;
$body-color: $o-main-text-color !default;
// Links
@@ -154,6 +154,7 @@ $table-th-font-weight: $headings-font-weight !default;
//
$btn-font-weight: $font-weight-bold !default;
$btn-disabled-opacity: $o-opacity-disabled !default;
$btn-border-radius-lg: $border-radius !default;
// Dropdowns
@@ -178,6 +179,7 @@ $dropdown-item-padding-x: $o-dropdown-hpadding !default;
$list-group-active-color: $o-list-group-active-color !default;
$list-group-active-bg: $o-list-group-active-bg !default;
$list-group-action-hover-color: $gray-900 !default;
// Z-index master list
@@ -3,6 +3,9 @@
/// They are available in every asset bundle.
///
// Color-scheme
$o-webclient-color-scheme: bright !default;
// Font sizes
$o-root-font-size: 12px !default;
$o-font-size-base: 13rem * (1px / $o-root-font-size) !default;
@@ -79,12 +82,12 @@ $o-form-lightsecondary: #ccc !default;
$o-list-footer-bg-color: #eee !default;
$o-list-footer-font-weight: bold !default;
$o-tooltip-background-color: white !default;
$o-tooltip-background-color: $o-view-background-color !default;
$o-tooltip-color: #666666 !default;
$o-tooltip-arrow-color: white !default;
$o-tooltip-text-color: #777777 !default;
$o-tooltip-title-text-color: black !default;
$o-tooltip-title-background-color: #F7F7F7 !default;
$o-tooltip-text-color: $o-main-text-color !default;
$o-tooltip-title-text-color: $o-main-headings-color !default;
$o-tooltip-title-background-color: $o-view-background-color !default;
// Forms
@@ -170,6 +173,10 @@ $o-border-radius-sm: .2rem !default;
$o-touch-btn-padding: 7px 14px !default;
// Buttons
$o-btn-secondary-bg: white !default;
$o-btn-secondary-bg: $o-white !default;
$o-btn-secondary-hover-bg: $o-gray-100 !default;
$o-btn-secondary-hover-border: $o-gray-200 !default;
$o-btn-light-bg: $o-white !default;
$o-btn-light-border: $o-btn-light-bg !default;
$o-btn-light-background-hover: $o-gray-100 !default;
@@ -13,8 +13,10 @@ $o-colors-secondary: #aa4b6b, #30C381, #97743a, #F7CD1F, #4285F4, #8E24AA,
#6be585, #999966, #e9d362, #b56969, #bdc3c7, #649173 !default;
// UI custom colors, complete list
$o-colors-complete-first: #134E5E !default;
$o-colors-complete: join(
set-nth($o-colors, 1, #134E5E),
set-nth($o-colors, 1, $o-colors-complete-first),
$o-colors-secondary
)!default;
@@ -77,9 +77,10 @@ $utilities: map-merge(
"background-color": map-merge(
map-get($utilities, "background-color"),
(
values: map-merge($utilities-bg-colors,
values: map-merge(
map-get(map-get($utilities, "background-color"), "values"),
(
"view": $o-view-background-color,
"view": $o-view-background-color,
)
)
)
@@ -0,0 +1,12 @@
// = Search Bar
// ============================================================================
.o_searchview_facet {
.o_facet_values {
border: $border-width solid var(--SearchBar-facet-background, #{$o-brand-odoo});
}
.o_searchview_facet_label {
background: var(--SearchBar-facet-background, #{$o-brand-odoo});
color: var(--SearchBar-facet-color, #{$o-white});
}
}
@@ -10,12 +10,12 @@
t-on-keydown="ev => this.onFacetKeydown(facet, facet_index, ev)"
>
<t t-if="facet.icon">
<span t-attf-class="o_searchview_facet_label text-bg-odoo {{ facet.icon }}"/>
<span t-attf-class="o_searchview_facet_label {{ facet.icon }}"/>
</t>
<t t-else="">
<span class="o_searchview_facet_label text-bg-odoo" t-esc="facet.title"/>
<span class="o_searchview_facet_label" t-esc="facet.title"/>
</t>
<div class="o_facet_values border border-odoo border-start-0">
<div class="o_facet_values border-start-0">
<t t-foreach="facet.values" t-as="facetValue" t-key="facetValue_index">
<t t-if="!facetValue_first">
<span class="o_facet_values_sep" t-esc="facet.separator"/>
@@ -23,7 +23,7 @@
<span class="o_facet_value" t-esc="facetValue"/>
</t>
</div>
<i class="o_facet_remove oi oi-close"
<i class="o_facet_remove oi oi-close btn btn-link opacity-50 opacity-100-hover text-900"
role="img"
aria-label="Remove"
title="Remove"
@@ -42,6 +42,7 @@ $o-cw-filter-avatar-size: 20px;
margin: 0;
width: 100%;
padding: 0;
background-color: $o-view-background-color;
&,
td,
@@ -3,7 +3,7 @@
min-width: 0;
height: 100%;
background-color: map-get($grays, "100");
background: linear-gradient(-45deg, map-get($grays, "100"), white);
background: linear-gradient(-45deg, map-get($grays, "100"), $o-view-background-color);
.fc-event {
margin: 0 1px;
@@ -410,12 +410,12 @@
}
&.o_attendee_status_needsAction {
background-color: rgba(white, 0.9) !important;
background-color: rgba($o-view-background-color, 0.9) !important;
}
&.o_attendee_status_declined {
text-decoration: line-through;
background-color: rgba(white, 0.9) !important;
background-color: rgba($o-view-background-color, 0.9) !important;
}
}
}
@@ -654,19 +654,19 @@ $o-filter_colors: lighten(#000, 46.7%), #f06050, #f4a460, #f7cd1f, #6cc1ed, #814
&.o_attendee_status_alone,
&.o_attendee_status_needsAction {
background-color: rgba(white, 0.9) !important;
color: black;
background-color: rgba($o-view-background-color, 0.9) !important;
color: $o-black;
.fc-bg {
background-color: rgba(white, 0.9) !important;
background-color: rgba($o-view-background-color, 0.9) !important;
}
}
&.o_attendee_status_declined {
text-decoration: line-through;
background-color: rgba(white, 0.9) !important;
color: black;
background-color: rgba($o-view-background-color, 0.9) !important;
color: $o-black;
.fc-bg {
background-color: rgba(white, 0.9) !important;
background-color: rgba($o-view-background-color, 0.9) !important;
}
}
}
@@ -681,7 +681,7 @@ $o-filter_colors: lighten(#000, 46.7%), #f06050, #f4a460, #f7cd1f, #6cc1ed, #814
}
.o_cw_popover.o_calendar_color_#{$i - 1} {
$color-subdle: mix(white, $color, 90%);
$color-subdle: mix($o-white, $color, 85%);
.card-header,
.card-header .popover-header {
@@ -691,7 +691,7 @@ $o-filter_colors: lighten(#000, 46.7%), #f06050, #f4a460, #f7cd1f, #6cc1ed, #814
.card-header {
padding-left: 2px;
border-color: mix($card-border-color, mix(white, $color));
border-color: mix($card-border-color, mix($o-white, $color));
}
}
}
@@ -6,8 +6,10 @@ import { _lt } from "@web/core/l10n/translation";
import { registry } from "@web/core/registry";
import { formatText } from "../formatters";
import { standardFieldProps } from "../standard_field_props";
import { getCookie } from "web.utils.cookies";
const { Component, onWillStart, onWillUpdateProps, useEffect, useRef } = owl;
const colorSchemeCookie = getCookie("color_scheme");
export class AceField extends Component {
setup() {
@@ -46,6 +48,7 @@ export class AceField extends Component {
this.aceEditor.setOptions({
maxLines: Infinity,
showPrintMargin: false,
theme: (colorSchemeCookie && colorSchemeCookie === "dark" ? 'ace/theme/monokai' : ''),
});
this.aceEditor.$blockScrolling = true;
@@ -18,7 +18,7 @@ export class BadgeField extends Component {
get classFromDecoration() {
for (const decorationName in this.props.decorations) {
if (this.props.decorations[decorationName]) {
return `bg-${decorationName}`;
return `text-bg-${decorationName}`;
}
}
return "";
@@ -2,7 +2,7 @@
<templates id="template" xml:space="preserve">
<t t-name="web.BadgeField" owl="1">
<span t-if="props.value" class="badge rounded-pill bg-opacity-50" t-att-class="classFromDecoration" t-esc="formattedValue" />
<span t-if="props.value" class="badge rounded-pill" t-att-class="classFromDecoration" t-esc="formattedValue" />
</t>
</templates>
@@ -1,19 +1,14 @@
.o_field_image {
background-color: var(--ImageField-background-color, transparent);
button {
transition: opacity ease 400ms;
width: 26px;
height: 26px;
opacity: 0;
background: $white;
}
&:hover button {
@include o-hover-opacity(0.6, 0.9);
}
.o_mobile_controls {
button {
@include o-hover-opacity(0.6, 0.9);
width: 30px;
height: 30px;
padding: 6px !important;
@@ -2,8 +2,8 @@
<templates xml:space="preserve">
<t t-name="web.ImageField" owl="1">
<div class="d-inline-block position-relative">
<div t-attf-class="position-absolute w-100 bottom-0 {{isMobile ? 'o_mobile_controls' : ''}}" aria-atomic="true" t-att-style="sizeStyle">
<div class="d-inline-block position-relative opacity-trigger-hover">
<div t-attf-class="position-absolute d-flex justify-content-between w-100 bottom-0 opacity-0 opacity-100-hover {{isMobile ? 'o_mobile_controls' : ''}}" aria-atomic="true" t-att-style="sizeStyle">
<t t-if="!props.readonly">
<FileUploader
acceptedFileExtensions="props.acceptedFileExtensions"
@@ -12,23 +12,25 @@
>
<t t-set-slot="toggler">
<button
class="position-absolute bottom-0 start-0 border-0 rounded-circle m-1 p-1 fa fa-pencil fa-lg o_select_file_button"
class="o_select_file_button btn btn-light border-0 rounded-circle m-1 p-1"
data-tooltip="Edit"
aria-label="Edit"
/>
aria-label="Edit">
<i class="fa fa-pencil fa-fw"/>
</button>
</t>
<button
t-if="props.value and state.isValid"
class="position-absolute bottom-0 end-0 border-0 rounded-circle m-1 p-1 fa fa-trash-o fa-lg o_clear_file_button"
class="o_clear_file_button btn btn-light border-0 rounded-circle m-1 p-1"
data-tooltip="Clear"
aria-label="Clear"
t-on-click="onFileRemove"
/>
t-on-click="onFileRemove">
<i class="fa fa-trash-o fa-fw"/>
</button>
</FileUploader>
</t>
</div>
<img
class="img img-fluid"
class="img img-fluid w-100"
alt="Binary file"
t-att-src="getUrl(props.previewImage or props.name)"
t-att-name="props.name"
@@ -2,6 +2,7 @@
import { loadJS } from "@web/core/assets";
import { registry } from "@web/core/registry";
import { getColor, hexToRGBA } from "@web/views/graph/colors";
import { standardFieldProps } from "../standard_field_props";
const { Component, onWillStart, useEffect, useRef } = owl;
@@ -49,8 +50,8 @@ export class JournalDashboardGraphField extends Component {
const labels = this.data[0].values.map(function (pt) {
return pt.x;
});
const borderColor = this.data[0].is_sample_data ? "#dddddd" : "#875a7b";
const backgroundColor = this.data[0].is_sample_data ? "#ebebeb" : "#dcd0d9";
const borderColor = this.data[0].is_sample_data ? hexToRGBA(getColor(10), 0.1) : getColor(10);
const backgroundColor = this.data[0].is_sample_data ? hexToRGBA(getColor(10), 0.05) : hexToRGBA(getColor(10), 0.2);
return {
type: "line",
data: {
@@ -96,7 +97,7 @@ export class JournalDashboardGraphField extends Component {
data.push(pt.value);
labels.push(pt.label);
const color =
pt.type === "past" ? "#ccbdc8" : pt.type === "future" ? "#a5d8d7" : "#ebebeb";
pt.type === "past" ? getColor(13) : pt.type === "future" ? getColor(19) : "#ebebeb";
backgroundColor.push(color);
});
return {
@@ -153,21 +153,14 @@
.o_form_uri {
display: inline-block;
color: $link-color;
&:hover {
color: darken($link-color, 15%);
}
@include o-hover-text-color($link-color, $link-hover-color);
> span {
color: $o-main-text-color;
&:hover {
color: $o-main-text-color;
}
@include o-hover-text-color($o-main-text-color, $o-main-text-color);
}
> span:first-child {
color: $link-color;
&:hover {
color: darken($link-color, 15%);
}
@include o-hover-text-color($link-color, $link-hover-color);
}
}
@@ -364,7 +357,7 @@
&:hover, &:focus, &:active {
&:after {
border-left-color: map-get($grays, '100');
border-left-color: $o-btn-light-background-hover;
}
}
}
@@ -872,7 +865,7 @@
table-layout: fixed;
display: table;
td {
border: 1px solid #dee2e6;
border: 1px solid $table-border-color;
}
th, td {
padding: 0.75rem 0 0.75rem 0;
+33 -5
View File
@@ -1,6 +1,8 @@
/** @odoo-module **/
export const COLORS = [
import { getCookie } from "web.utils.cookies";
const COLORS_BRIGHT = [
"#1f77b4",
"#ff7f0e",
"#aec7e8",
@@ -11,18 +13,43 @@ export const COLORS = [
"#ff9896",
"#9467bd",
"#c5b0d5",
"#8c564b",
"#875a7b", // ~ Enterprise
"#c49c94",
"#e377c2",
"#f7b6d2",
"#dcd0d9", // Dashboards Primary
"#7f7f7f",
"#c7c7c7",
"#bcbd22",
"#dbdb8d",
"#17becf",
"#9edae5",
"#a5d8d7", // Dashboards Secondary
];
const COLORS_DARK = [
"#00ffff",
"#ff6347",
"#00ced1",
"#ffd700",
"#29ef29",
"#c5fabb",
"#fe4b4c",
"#ffb6c1",
"#ba87e9",
"#eadbf6",
"#c568af", // ~ Enterprise
"#ecc1b8",
"#fda9e3",
"#BB86FC", // Dashboards Primary
"#808080",
"#f2e8e8",
"#fcfe2d",
"#f8f8bc",
"#17becf",
"#10efed", // Dashboards Secondary
];
export const COLORS = getCookie("color_scheme") === "dark" ? COLORS_DARK : COLORS_BRIGHT;
/**
* @param {number} index
* @returns {string}
@@ -33,7 +60,8 @@ export function getColor(index) {
export const DEFAULT_BG = "#d3d3d3";
export const BORDER_WHITE = "rgba(255,255,255,0.6)";
export const BORDER_WHITE =
getCookie("color_scheme") === "dark" ? "rgba(0, 0, 0, 0.6)" : "rgba(255,255,255,0.6)";
const RGB_REGEX = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;
@@ -14,41 +14,41 @@
</div>
</t>
<div class="btn-group" role="toolbar" aria-label="Change graph">
<button class="btn btn-secondary fa fa-bar-chart o_graph_button" data-tooltip="Bar Chart" aria-label="Bar Chart" data-mode="bar"
<button class="btn btn-light fa fa-bar-chart o_graph_button" data-tooltip="Bar Chart" aria-label="Bar Chart" data-mode="bar"
t-on-click="() => this.onModeSelected('bar')"
t-att-class="{ active: model.metaData.mode === 'bar' }"
/>
<button class="btn btn-secondary fa fa-line-chart o_graph_button" data-tooltip="Line Chart" aria-label="Line Chart" data-mode="line"
<button class="btn btn-light fa fa-line-chart o_graph_button" data-tooltip="Line Chart" aria-label="Line Chart" data-mode="line"
t-on-click="() => this.onModeSelected('line')"
t-att-class="{ active: model.metaData.mode === 'line' }"
/>
<button class="btn btn-secondary fa fa-pie-chart o_graph_button" data-tooltip="Pie Chart" aria-label="Pie Chart" data-mode="pie"
<button class="btn btn-light fa fa-pie-chart o_graph_button" data-tooltip="Pie Chart" aria-label="Pie Chart" data-mode="pie"
t-on-click="() => this.onModeSelected('pie')"
t-att-class="{ active: model.metaData.mode === 'pie' }"
/>
</div>
<div t-if="model.metaData.mode === 'bar'" class="btn-group" role="toolbar" aria-label="Change graph">
<button class="btn btn-secondary fa fa-database o_graph_button" data-tooltip="Stacked" aria-label="Stacked"
<button class="btn btn-light fa fa-database o_graph_button" data-tooltip="Stacked" aria-label="Stacked"
t-on-click="toggleStacked"
t-att-class="{ active: model.metaData.stacked }"
/>
</div>
<div t-if="model.metaData.mode === 'line'" class="btn-group" role="toolbar" aria-label="Change graph">
<button class="btn btn-secondary fa fa-database o_graph_button" data-tooltip="Stacked" aria-label="Stacked"
<button class="btn btn-light fa fa-database o_graph_button" data-tooltip="Stacked" aria-label="Stacked"
t-on-click="toggleStacked"
t-att-class="{ active: model.metaData.stacked }"
/>
<button class="btn btn-secondary fa fa-signal o_graph_button" data-tooltip="Cumulative" aria-label="Cumulative"
<button class="btn btn-light fa fa-signal o_graph_button" data-tooltip="Cumulative" aria-label="Cumulative"
t-on-click="toggleCumulated"
t-att-class="{ active: model.metaData.cumulated }"
/>
</div>
<div t-if="model.metaData.mode !== 'pie' and model.metaData.domains.length === 1" class="btn-group" role="toolbar" aria-label="Sort graph" name="toggleOrderToolbar">
<button class="btn btn-secondary fa fa-sort-amount-desc o_graph_button" data-tooltip="Descending" aria-label="Descending"
<button class="btn btn-light fa fa-sort-amount-desc o_graph_button" data-tooltip="Descending" aria-label="Descending"
t-on-click="() => this.toggleOrder('DESC')"
t-att-class="{ active: model.metaData.order === 'DESC' }"
/>
<button class="btn btn-secondary fa fa-sort-amount-asc o_graph_button" data-tooltip="Ascending" aria-label="Ascending"
<button class="btn btn-light fa fa-sort-amount-asc o_graph_button" data-tooltip="Ascending" aria-label="Ascending"
t-on-click="() => this.toggleOrder('ASC')"
t-att-class="{ active: model.metaData.order === 'ASC' }"
/>
@@ -3,7 +3,7 @@
<t t-name="web.GraphRenderer.CustomTooltip" owl="1">
<div class="o_graph_custom_tooltip popover show p-2 pe-none mw-100">
<table class="table table-borderless table-sm overflow-hidden m-0">
<table class="overflow-hidden m-0">
<thead>
<tr>
<th class="o_measure align-baseline border-0" t-esc="measure" />
@@ -222,6 +222,8 @@
// (eg. Company logo badge inside a contact picture)
.o_kanban_image_fill_left,
.o_kanban_image {
background-color: var(--KanbanRecord__image-bg-color, none);
.o_kanban_image_inner_pic {
@include o-position-absolute($right: 0, $bottom: 0);
max: {
@@ -445,7 +447,7 @@
}
.oe_kanban_text_red {
color: #a61300;
color: o-text-color('danger');
font-weight: $font-weight-bold;
}
@@ -522,7 +524,8 @@
// don't visually fold on smaller screens (aka. mobile)
@include media-breakpoint-up(md) {
@include o-kanban-slim-col;
background-color: $gray-200;
background-color: var(--KanbanGroup-grouped-bg, #{$gray-200});
& + .o_kanban_group.o_column_folded {
margin-left: 1px;
@@ -5,18 +5,18 @@
<div class="o_pivot table-responsive">
<table
class="table-hover table table-sm table-bordered table-borderless bg-white"
class="table-hover table table-sm table-bordered table-borderless bg-view"
t-att-class="{ o_enable_linking: !model.metaData.disableLinking }"
t-ref="table"
>
<thead>
<tr t-foreach="table.headers" t-as="row" t-key="'header_' + row_index">
<tr t-foreach="table.headers" t-as="row" t-key="'header_' + row_index" class="border-top-0">
<t t-foreach="row" t-as="cell" t-key="'header_row_' + cell_index">
<t t-if="cell.measure" t-call="web.PivotMeasure"/>
<t t-elif="cell.isLeaf !== undefined" t-call="web.PivotHeader">
<t t-set="isXAxis" t-value="true"/>
</t>
<th t-else="" t-att-colspan="cell.width" t-att-rowspan="cell.height" class="fw-normal bg-100"/>
<th t-else="" t-att-colspan="cell.width" t-att-rowspan="cell.height" class="fw-normal border-start-0"/>
</t>
</tr>
</thead>
@@ -27,7 +27,7 @@
<t t-set="cell" t-value="row"/>
</t>
<t t-foreach="row.subGroupMeasurements" t-as="cell" t-key="'row_cell_' + cell_index">
<td class="o_pivot_cell_value text-end" t-att-class="{
<td class="o_pivot_cell_value text-end bg-100" t-att-class="{
o_empty: cell.value === undefined,
'cursor-pointer': cell.value !== undefined,
'fw-bold': cell.isBold,
@@ -54,7 +54,7 @@
<t t-name="web.PivotHeader" owl="1">
<th
class="text-nowrap cursor-pointer fw-normal bg-100 user-select-none"
class="text-nowrap cursor-pointer fw-normal user-select-none border-start-0"
t-att-colspan="isXAxis ? cell.width : undefined"
t-att-rowspan="isXAxis ? cell.height : undefined"
t-att-class="{
@@ -90,7 +90,7 @@
</t>
<t t-name="web.PivotMeasure" owl="1">
<th class="text-muted text-center text-nowrap fw-normal bg-100" t-att-colspan="cell.width" t-att-rowspan="cell.height" t-att-class="{
<th class="text-muted text-center text-nowrap fw-normal" t-att-colspan="cell.width" t-att-rowspan="cell.height" t-att-class="{
'o_pivot_origin_row cursor-pointer user-select-none': cell.originIndexes,
'o_pivot_measure_row cursor-pointer user-select-none': !cell.originIndexes,
o_pivot_sort_order_asc: cell.order === 'asc',
+2 -2
View File
@@ -11,7 +11,7 @@
.o_nocontent_help {
border-radius: 20%;
background-color: #f9f9f9;
box-shadow: 0 0 120px 100px #f9f9f9;
background-color: $o-view-background-color;
box-shadow: 0 0 120px 100px $o-view-background-color;
}
}
@@ -14,13 +14,11 @@
transform: translateX(0);
}
// Scoped variables
$-base-bg: $o-brand-odoo; // change to get variations on the fly (eg. 'dark mode')
$-base-color: color-contrast($-base-bg);
// ====== Top-Bar
.o_burger_menu_topbar {
min-height: $o-navbar-height-xs;
background-color: $o-burger-topbar-bg;
color: $o-burger-topbar-color;
line-height: $o-navbar-height-xs;
.dropdown-toggle, .o_burger_menu_close {
@@ -31,13 +29,13 @@
// ====== Menu content container (both App's and User's entries)
.o_burger_menu_content {
&.o_burger_menu_dark {
background-color: darken($-base-bg, 5%);
background-color: darken($o-burger-base-bg, 5%);
}
// Menu entries size and layout
ul {
background-color: rgba(invert($-base-color), .1);
box-shadow: inset 0 -1px 0 rgba($-base-color, .1);
background-color: rgba(invert($o-burger-base-color), .1);
box-shadow: inset 0 -1px 0 rgba($o-burger-base-color, .1);
li > div, li {
padding-left: $o-horizontal-padding;
@@ -59,7 +57,7 @@
}
li, button {
@include o-hover-text-color(rgba($-base-color, .8), $-base-color);
@include o-hover-text-color(rgba($o-burger-base-color, .8), $o-burger-base-color);
}
// ====== 'User Menu' spefic design rules
@@ -0,0 +1,7 @@
// = Burger Menu Variables
// ============================================================================
$o-burger-topbar-bg: $o-brand-odoo !default;
$o-burger-topbar-color: $o-white !default;
$o-burger-base-bg: $o-burger-topbar-bg !default;
$o-burger-base-color: $o-burger-topbar-color !default;
@@ -13,9 +13,9 @@
<t t-portal="'body'">
<Transition name="'burgerslide'" visible="state.isBurgerOpened" leaveDuration="200" t-slot-scope="transition">
<div class="o_burger_menu position-fixed top-0 bottom-0 start-100 d-flex flex-column flex-nowrap" t-att-class="transition.className" t-on-touchstart.stop="_onSwipeStart" t-on-touchend.stop="_onSwipeEnd">
<div class="o_burger_menu_topbar d-flex align-items-center justify-content-between flex-shrink-0 py-0 text-bg-odoo fs-4"
<div class="o_burger_menu_topbar d-flex align-items-center justify-content-between flex-shrink-0 py-0 fs-4"
t-on-click.stop='_toggleUserMenu'>
<small class="o-no-caret dropdown-toggle d-flex align-items-center justify-content-between" t-att-class="{'active bg-white': isUserMenuUnfolded }">
<small class="o-no-caret dropdown-toggle d-flex align-items-center justify-content-between" t-att-class="{'active bg-view': isUserMenuUnfolded }">
<img class="o_burger_menu_avatar o_image_24_cover rounded-circle" t-att-src="'/web/image?model=res.users&amp;field=avatar_128&amp;id=' + user.userId" alt="Menu"/>
<span class="o_burger_menu_username px-2"><t t-esc="user.name"/></span>
<i t-if="isUserMenuTogglable" class="fa" t-att-class="state.isUserMenuOpened ? 'fa-caret-down' : 'fa-caret-left'"/>
@@ -23,7 +23,7 @@
<button class="o_burger_menu_close oi oi-close btn d-flex align-items-center h-100 bg-transparent border-0 fs-2 text-reset" aria-label="Close menu" title="Close menu" t-on-click.stop="_closeBurger"/>
</div>
<nav class="o_burger_menu_content flex-grow-1 flex-shrink-1 overflow-auto"
t-att-class="{o_burger_menu_dark: !isUserMenuUnfolded, 'bg-white': isUserMenuUnfolded}">
t-att-class="{o_burger_menu_dark: !isUserMenuUnfolded, 'bg-view': isUserMenuUnfolded}">
<!-- -->
<t t-if="isUserMenuUnfolded">
<MobileSwitchCompanyMenu t-if="Object.values(company.availableCompanies).length > 1" />
@@ -104,7 +104,8 @@
padding: ($o-navbar-badge-padding * .5) $o-navbar-badge-padding;
background-color: var(--o-navbar-badge-bg, #{$o-navbar-badge-bg});
font-size: $o-navbar-badge-size;
text-shadow: 1px 1px 0 rgba(#000, .3);
color: var(--o-navbar-badge-color, inherit);
text-shadow: var(--o-navbar-badge-text-shadow, #{1px 1px 0 rgba($black, .3)});
transform: translate(-10%, -30%);
}
}
@@ -77,6 +77,11 @@
// BASE SETTINGS LAYOUT
.o_base_settings {
--settings__tab-bg: #{map-get($grays, '900')};
--settings__tab-bg--active: #{map-get($grays, '800')};
--settings__tab-color: #{map-get($grays, '400')};
--settings__title-bg: #{map-get($grays, '200')};
height: 100%;
.o_control_panel {
@@ -125,18 +130,17 @@
.o_setting_container {
display: flex;
flex: 1 1 auto;
overflow: auto;
.settings_tab {
display: flex;
flex: 0 0 auto;
flex-flow: column nowrap;
background: map-get($grays, '900');
background: var(--settings__tab-bg);
overflow: auto;
.selected {
background-color: map-get($grays, '800');
background-color: var(--settings__tab-bg--active);
box-shadow: inset 2px 0 0 $o-brand-primary;
}
@@ -144,7 +148,7 @@
display: flex;
padding: 0 $o-horizontal-padding*2 0 $o-horizontal-padding;
height: 40px;
color: map-get($grays, '400');
color: var(--settings__tab-color);
font-size: 13px;
line-height: 40px;
cursor: pointer;
@@ -172,7 +176,7 @@
h2 {
margin: 0 0 !important;
@include o-base-settings-horizontal-padding(.4rem);
background-color: map-get($grays, '200');
background-color: var(--settings__title-bg);
font-size: 15px;
&.o_invisible_modifier + .o_settings_container {
@@ -13,12 +13,11 @@
.settings_tab {
flex: 0 0 $o-base-settings-mobile-tabs-height;
flex-direction: row;
justify-content: space-between;
position: relative;
overflow: hidden;
overflow-x: auto;
padding: 0;
background: #5E5E5E;
border-bottom: 1px solid $border-color;
.tab {
display: block;
@@ -49,7 +48,6 @@
}
&.current {
color: white;
font-weight: bold;
// Reset default style for 'selected' tabs
@@ -2,6 +2,7 @@
import { Dropdown } from "@web/core/dropdown/dropdown";
import { DropdownItem } from "@web/core/dropdown/dropdown_item";
import { CheckBox } from "@web/core/checkbox/checkbox";
import { browser } from "@web/core/browser/browser";
import { registry } from "@web/core/registry";
import { useService } from "@web/core/utils/hooks";
@@ -31,7 +32,7 @@ export class UserMenu extends Component {
}
}
UserMenu.template = "web.UserMenu";
UserMenu.components = { Dropdown, DropdownItem };
UserMenu.components = { Dropdown, DropdownItem, CheckBox };
export const systrayItem = {
Component: UserMenu,
@@ -10,12 +10,21 @@
<t t-foreach="getElements()" t-as="element" t-key="element_index">
<t t-if="!element.hide">
<DropdownItem
t-if="element.type == 'item'"
t-if="element.type == 'item' || element.type == 'switch'"
href="element.href"
dataset="{ menu: element.id }"
t-esc="element.description"
onSelected="element.callback"
/>
>
<CheckBox
t-if="element.type == 'switch'"
value="element.isChecked"
className="'form-switch d-flex flex-row-reverse justify-content-between p-0'"
onChange="element.callback"
>
<t t-out="element.description"/>
</CheckBox>
<t t-else="" t-out="element.description"/>
</DropdownItem>
<div t-if="element.type == 'separator'" role="separator" class="dropdown-divider"/>
</t>
</t>
+11 -9
View File
@@ -1,4 +1,6 @@
:root {
--o-webclient-color-scheme:#{$o-webclient-color-scheme};
font-size: $o-root-font-size;
}
@@ -22,6 +24,7 @@ tfoot {
direction: ltr;
position: relative; // normally useless but required by bootstrap-datepicker
background-color: $o-webclient-background-color;
color-scheme: $o-webclient-color-scheme;
}
// ------------------------------------------------------------------
@@ -207,8 +210,7 @@ select {
@mixin o-placeholder {
// Rules below need to be separeted. Otherwise all browsers will discard the whole rule.
color: $o-brand-secondary;
opacity: 0.5;
color: $input-placeholder-color;
}
::-webkit-input-placeholder {
// WebKit, Blink, Edge
@@ -249,7 +251,7 @@ select {
@include o-hover-text-color($link-color, $link-hover-color);
&.disabled, &:disabled {
@include o-hover-text-color($link-color, $link-color);
@include o-hover-text-color($o-gray-500, $o-gray-500);
}
}
@@ -272,12 +274,12 @@ select {
// Achieve "clickable text" elements that act like buttons once the
// the user interacts with (eg. control-panel dropdowns);
@include button-variant(
$background: #fff,
$border: #fff,
$hover-background: $o-gray-100,
$hover-border: $o-gray-200,
$active-background: $o-gray-100,
$active-border: $o-gray-300
$background: $o-btn-light-bg,
$border: $o-btn-light-border,
$hover-background: $o-btn-light-background-hover,
$hover-border: $o-btn-light-background-hover,
$active-background: $o-btn-light-background-hover,
$active-border: $o-btn-light-background-hover
);
}
@@ -9289,14 +9289,14 @@ QUnit.module('Legacy basic_fields', {
});
assert.containsN(list, '.o_field_badge[name="foo"]', 5);
assert.containsOnce(list, '.o_field_badge[name="foo"].bg-danger.bg-opacity-50');
assert.containsOnce(list, '.o_field_badge[name="foo"].bg-warning.bg-opacity-50');
assert.containsOnce(list, '.o_field_badge[name="foo"].text-bg-danger.bg-opacity-50');
assert.containsOnce(list, '.o_field_badge[name="foo"].text-bg-warning.bg-opacity-50');
await list.reload();
assert.containsN(list, '.o_field_badge[name="foo"]', 5);
assert.containsOnce(list, '.o_field_badge[name="foo"].bg-danger.bg-opacity-50');
assert.containsOnce(list, '.o_field_badge[name="foo"].bg-warning.bg-opacity-50');
assert.containsOnce(list, '.o_field_badge[name="foo"].text-bg-danger.bg-opacity-50');
assert.containsOnce(list, '.o_field_badge[name="foo"].text-bg-warning.bg-opacity-50');
list.destroy();
});
@@ -9908,14 +9908,14 @@ QUnit.module('Legacy fields', {}, function () {
});
assert.containsN(form, '.o_data_row', 2);
assert.hasClass(form.$('.o_data_row:nth(1) .o_field_badge'), 'bg-warning');
assert.hasClass(form.$('.o_data_row:nth(1) .o_field_badge'), 'text-bg-warning');
await testUtils.dom.click(form.$('.o_data_row .o_data_cell:first'));
await testUtils.owlCompatibilityExtraNextTick();
await testUtils.fields.editInput(form.$('.o_selected_row .o_field_integer'), '44');
await testUtils.owlCompatibilityExtraNextTick();
assert.hasClass(form.$('.o_data_row:nth(1) .o_field_badge'), 'bg-warning');
assert.hasClass(form.$('.o_data_row:nth(1) .o_field_badge'), 'text-bg-warning');
form.destroy();
});
@@ -124,7 +124,7 @@ QUnit.module("Fields", (hooks) => {
});
assert.containsN(target, '.o_field_badge[name="display_name"]', 4);
assert.containsOnce(target, '.o_field_badge[name="display_name"] .bg-danger');
assert.containsOnce(target, '.o_field_badge[name="display_name"] .bg-warning');
assert.containsOnce(target, '.o_field_badge[name="display_name"] .text-bg-danger');
assert.containsOnce(target, '.o_field_badge[name="display_name"] .text-bg-warning');
});
});
@@ -10796,7 +10796,7 @@ QUnit.module("Fields", (hooks) => {
assert.containsN(target, ".o_data_row", 2);
assert.hasClass(
target.querySelectorAll(".o_data_row")[1].querySelector(".o_field_badge .badge"),
"bg-warning"
"text-bg-warning"
);
await click(target.querySelector(".o_data_row .o_data_cell"));
@@ -10804,7 +10804,7 @@ QUnit.module("Fields", (hooks) => {
assert.hasClass(
target.querySelectorAll(".o_data_row")[1].querySelector(".o_field_badge .badge"),
"bg-warning"
"text-bg-warning"
);
});
@@ -57,6 +57,17 @@ QUnit.test("can be rendered", async (assert) => {
sequence: 5,
};
});
userMenuRegistry.add("frodo_item", function () {
return {
type: "switch",
id: "frodo",
description: "Frodo",
callback: () => {
assert.step("callback frodo_item");
},
sequence: 11,
};
});
userMenuRegistry.add("separator", function () {
return {
type: "separator",
@@ -93,26 +104,27 @@ QUnit.test("can be rendered", async (assert) => {
assert.strictEqual(target.querySelector(".oe_topbar_name").textContent, "Sauron");
assert.containsNone(target, ".dropdown-menu .dropdown-item");
await click(target.querySelector("button.dropdown-toggle"));
assert.containsN(target, ".dropdown-menu .dropdown-item", 3);
assert.containsN(target, ".dropdown-menu .dropdown-item", 4);
assert.containsOnce(target, ".dropdown-menu .dropdown-item input.form-check-input");
assert.containsOnce(target, "div.dropdown-divider");
const children = [...(target.querySelector(".dropdown-menu").children || [])];
assert.deepEqual(
children.map((el) => el.tagName),
["SPAN", "SPAN", "DIV", "SPAN"]
["SPAN", "SPAN", "SPAN", "DIV", "SPAN"]
);
const items = [...target.querySelectorAll(".dropdown-menu .dropdown-item")] || [];
assert.deepEqual(
items.map((el) => el.dataset.menu),
["ring", "bad", "eye"]
["ring", "bad", "frodo", "eye"]
);
assert.deepEqual(
items.map((el) => el.textContent),
["Ring", "Bad", "Eye"]
["Ring", "Bad", "Frodo", "Eye"]
);
for (const item of items) {
click(item);
}
assert.verifySteps(["callback ring_item", "callback bad_item", "callback eye_item"]);
assert.verifySteps(["callback ring_item", "callback bad_item", "callback frodo_item", "callback eye_item"]);
});
QUnit.test("display the correct name in debug mode", async (assert) => {
@@ -24,6 +24,10 @@
background: white center top;
background-size: cover;
.o_onboarding_btn_close {
color: #fff;
}
// = Color Variations
// ------------------------------------------------------------------------
@each $key, $values in $o-onboarding-colors {
@@ -66,6 +70,7 @@
.o_onboarding_step_action {
min-width: $o-onboarding-step-width * .5;
border: $border-width solid #fff;
}
.o_onboarding_progress {
@@ -91,6 +96,13 @@
display: none;
}
.o_onboarding_step_title,
.o_onboarding_step_action,
.o_onboarding_step_action__done,
.o_onboarding_dot_isChecked {
color: #fff;
}
// = "To do" Step Design
// --------------------------------------------------------------------
&[data-step-state="not_done"] {
+7 -7
View File
@@ -28,7 +28,7 @@
t-att-style="'background-image:url(' + bg_image + ')'">
<div class="o_onboarding_wrap py-5">
<a href="#" data-bs-toggle="modal" data-bs-target=".o_onboarding_modal" class="o_onboarding_btn_close position-absolute top-0 end-0 py-2 px-3 h2 text-white" title="Close the onboarding panel"><i class="oi oi-close"/></a>
<a href="#" data-bs-toggle="modal" data-bs-target=".o_onboarding_modal" class="o_onboarding_btn_close position-absolute top-0 end-0 py-2 px-3 h2" title="Close the onboarding panel"><i class="oi oi-close"/></a>
<div class="o_onboarding_steps d-flex" t-out="0"/>
@@ -55,24 +55,24 @@
<div class="o_onboarding_step_side d-flex pt-0 flex-grow-1">
<div class="o_onboarding_progress position-absolute"/>
<span t-attf-class="o_onboarding_dot fa fa-check d-inline-block rounded-circle small {{state != 'not_done' and 'text-white' or ''}}"/>
<span t-attf-class="o_onboarding_dot fa fa-check d-inline-block rounded-circle small {{state != 'not_done' and 'o_onboarding_dot_isChecked' or ''}}"/>
</div>
<div class="o_onboarding_step_content py-3 flex-grow-1 d-flex flex-column align-items-center justify-content-around">
<div class="o_onboarding_step_content_info mb-3">
<a type="action" data-reload-on-close="true" role="button" t-att-data-method="method" t-att-data-model="model">
<h4 class="o_onboarding_step_title text-white" t-out="title"/>
<h4 class="o_onboarding_step_title" t-out="title"/>
</a>
<p class="text-white-75 m-0" t-out="description"/>
</div>
<a t-if="state == 'not_done'" class="o_onboarding_step_action btn px-4 border border-white" type="action" data-reload-on-close="true" role="button" t-att-data-method="method" t-att-data-model="model">
<span class="text-white">
<a t-if="state == 'not_done'" class="o_onboarding_step_action btn px-4" type="action" data-reload-on-close="true" role="button" t-att-data-method="method" t-att-data-model="model">
<span>
<t t-if="btn_text" t-out="btn_text" />
<t t-else="">Let's do it</t>
</span>
</a>
<a t-else="" class="o_onboarding_step_action__done btn text-white" type="action" data-reload-on-close="true" role="button" t-att-data-method="method" t-att-data-model="model">
<span class="text-white">
<a t-else="" class="o_onboarding_step_action__done btn" type="action" data-reload-on-close="true" role="button" t-att-data-method="method" t-att-data-model="model">
<span>
<i t-attf-class="me-2 fa #{done_icon if done_icon else 'fa-check'}" />
<t t-if="done_text" t-out="done_text" />
<t t-else="">All done!</t>