[FIX] web: Prevent drag on kanban record dropdown
Before this commit, clicking on any part of a kanban record would initiate a drag & drop sequence, this included its dropdown. This caused 2 issues: - You could start to drag & drop records by dragging their still opened dropdowns ; - Said dropdowns would remain open when dragging their parent record. This commit fixes both of these issues by hiding dropdowns during drag sequences and preventing drag when clicking inside the dropdowns. closes odoo/odoo#98791 Signed-off-by: Simon Genin (ges@odoo) <ges@odoo.com>
This commit is contained in:
@@ -3,15 +3,17 @@
|
||||
display: flex;
|
||||
align-content: stretch;
|
||||
|
||||
.dropdown, .o_kanban_manage_button_section {
|
||||
.dropdown,
|
||||
.o_kanban_manage_button_section {
|
||||
position: inherit;
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
padding: 0px!important;
|
||||
padding: 0px !important;
|
||||
}
|
||||
|
||||
.o_kanban_record > div, .o_kanban_quick_create {
|
||||
.o_kanban_record > div,
|
||||
.o_kanban_quick_create {
|
||||
padding: $o-kanban-inside-vgutter $o-kanban-inside-hgutter;
|
||||
border: 1px solid $border-color;
|
||||
background-color: $o-view-background-color;
|
||||
@@ -19,7 +21,8 @@
|
||||
@include media-breakpoint-down(md) {
|
||||
padding: $o-kanban-inside-vgutter $o-kanban-inside-hgutter-mobile;
|
||||
}
|
||||
&:focus, &:focus-within {
|
||||
&:focus,
|
||||
&:focus-within {
|
||||
z-index: 1; // show the shadow on top of the previous & next cards in grouped mode
|
||||
outline: none;
|
||||
}
|
||||
@@ -37,7 +40,7 @@
|
||||
}
|
||||
|
||||
.o_kanban_cancel {
|
||||
color: map-get($grays, '600'); // to make color uniform in community and enterprise
|
||||
color: map-get($grays, "600"); // to make color uniform in community and enterprise
|
||||
}
|
||||
|
||||
&.o_disabled {
|
||||
@@ -69,15 +72,17 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
width: 100%,
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
// Inner Sections
|
||||
.o_kanban_record_top, .o_kanban_record_body {
|
||||
.o_kanban_record_top,
|
||||
.o_kanban_record_body {
|
||||
margin-bottom: $o-kanban-inner-hmargin;
|
||||
}
|
||||
|
||||
.o_kanban_record_top, .o_kanban_record_bottom {
|
||||
.o_kanban_record_top,
|
||||
.o_kanban_record_bottom {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@@ -109,7 +114,7 @@
|
||||
|
||||
.o_kanban_record_subtitle {
|
||||
display: block;
|
||||
margin-top: $o-kanban-inner-hmargin*0.5;
|
||||
margin-top: $o-kanban-inner-hmargin * 0.5;
|
||||
|
||||
i.fa[role="img"] {
|
||||
margin-right: 2px;
|
||||
@@ -117,7 +122,8 @@
|
||||
}
|
||||
|
||||
.o_kanban_record_bottom {
|
||||
.oe_kanban_bottom_left, .oe_kanban_bottom_right {
|
||||
.oe_kanban_bottom_left,
|
||||
.oe_kanban_bottom_right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: 20px;
|
||||
@@ -135,14 +141,15 @@
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
.oe_kanban_bottom_right{
|
||||
.oe_kanban_bottom_right {
|
||||
flex: 0 1 auto;
|
||||
|
||||
.oe_kanban_avatar {
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.oe_kanban_avatar, .o_field_many2one_avatar > .o_m2o_avatar {
|
||||
.oe_kanban_avatar,
|
||||
.o_field_many2one_avatar > .o_m2o_avatar {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-left: 6px;
|
||||
@@ -151,7 +158,7 @@
|
||||
.o_link_muted {
|
||||
color: $body-color;
|
||||
&:hover {
|
||||
color: map-get($theme-colors, 'primary');
|
||||
color: map-get($theme-colors, "primary");
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
@@ -165,12 +172,12 @@
|
||||
|
||||
.o_kanban_image_fill_left {
|
||||
position: relative;
|
||||
margin-right: $o-kanban-inside-hgutter*2;
|
||||
margin-right: $o-kanban-inside-hgutter * 2;
|
||||
@include media-breakpoint-up(sm) {
|
||||
margin: {
|
||||
top: $o-kanban-inside-vgutter*-1;
|
||||
bottom: $o-kanban-inside-vgutter*-1;
|
||||
left: $o-kanban-inside-hgutter*-1;
|
||||
top: $o-kanban-inside-vgutter * -1;
|
||||
bottom: $o-kanban-inside-vgutter * -1;
|
||||
left: $o-kanban-inside-hgutter * -1;
|
||||
}
|
||||
}
|
||||
flex: 1 0 $o-kanban-image-fill-width;
|
||||
@@ -179,7 +186,7 @@
|
||||
size: cover;
|
||||
position: center;
|
||||
repeat: no-repeat;
|
||||
};
|
||||
}
|
||||
|
||||
&.o_kanban_image_full {
|
||||
background-size: contain;
|
||||
@@ -191,7 +198,7 @@
|
||||
// Eg. In partners list we use to fill user picture only, keeping the
|
||||
// default design for company logos.
|
||||
.o_kanban_image {
|
||||
margin-right: $o-kanban-inside-hgutter*2;
|
||||
margin-right: $o-kanban-inside-hgutter * 2;
|
||||
flex: 0 0 $o-kanban-image-width;
|
||||
min-height: $o-kanban-image-width;
|
||||
align-self: center;
|
||||
@@ -203,8 +210,12 @@
|
||||
|
||||
// On medium screen size, align 'o_kanban_image' to 'o_kanban_image_fill_left' elements.
|
||||
@include media-breakpoint-up(md) {
|
||||
$fill-notfill-gap: ($o-kanban-image-fill-width - $o-kanban-inside-hgutter*2) - $o-kanban-image-width;
|
||||
margin: { left: $fill-notfill-gap*0.5; right: $fill-notfill-gap*2;}
|
||||
$fill-notfill-gap: ($o-kanban-image-fill-width - $o-kanban-inside-hgutter * 2) -
|
||||
$o-kanban-image-width;
|
||||
margin: {
|
||||
left: $fill-notfill-gap * 0.5;
|
||||
right: $fill-notfill-gap * 2;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
@@ -214,16 +225,20 @@
|
||||
|
||||
// Reset immedialy after div padding
|
||||
+ div {
|
||||
padding-left: 0
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Images (backgrounds) could accomodate another image inside.
|
||||
// (eg. Company logo badge inside a contact picture)
|
||||
.o_kanban_image_fill_left, .o_kanban_image {
|
||||
.o_kanban_image_fill_left,
|
||||
.o_kanban_image {
|
||||
.o_kanban_image_inner_pic {
|
||||
@include o-position-absolute($right: 0, $bottom:0);
|
||||
max: { height: 25px; width: 80%;}
|
||||
@include o-position-absolute($right: 0, $bottom: 0);
|
||||
max: {
|
||||
height: 25px;
|
||||
width: 80%;
|
||||
}
|
||||
background: white;
|
||||
box-shadow: -1px -1px 0 1px white;
|
||||
}
|
||||
@@ -235,6 +250,10 @@
|
||||
@extend .shadow;
|
||||
transform: rotate(-3deg);
|
||||
transition: transform 0.6s, box-shadow 0.3s;
|
||||
|
||||
.dropdown {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
// ------- Compatibility of old (<= v10) Generic layouts -------
|
||||
@@ -242,7 +261,8 @@
|
||||
// Kanban Records - Uniform Design
|
||||
// Provide a basic style for different kanban record layouts
|
||||
// ---------------------------------------------------------
|
||||
.oe_kanban_card, .o_kanban_record {
|
||||
.oe_kanban_card,
|
||||
.o_kanban_record {
|
||||
// ------- v11 Layout + generic layouts (~v10) -------
|
||||
// Kanban Record - Dropdown
|
||||
.o_dropdown_kanban {
|
||||
@@ -265,7 +285,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .o_dropdown_kanban, .o_dropdown_kanban.show {
|
||||
&:hover .o_dropdown_kanban,
|
||||
.o_dropdown_kanban.show {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
@@ -275,7 +296,8 @@
|
||||
}
|
||||
|
||||
// Kanban Record - Inner elements
|
||||
.o_field_many2many_tags, .o_kanban_tags {
|
||||
.o_field_many2many_tags,
|
||||
.o_kanban_tags {
|
||||
display: block;
|
||||
margin-bottom: $o-kanban-inner-hmargin;
|
||||
line-height: 1.2;
|
||||
@@ -329,8 +351,12 @@
|
||||
.o_kanban_button {
|
||||
margin-top: 15px;
|
||||
|
||||
> button, > a {
|
||||
@include o-position-absolute($right: $o-kanban-record-margin, $bottom: $o-kanban-record-margin);
|
||||
> button,
|
||||
> a {
|
||||
@include o-position-absolute(
|
||||
$right: $o-kanban-record-margin,
|
||||
$bottom: $o-kanban-record-margin
|
||||
);
|
||||
@include media-breakpoint-down(md) {
|
||||
right: $o-kanban-inside-hgutter-mobile;
|
||||
}
|
||||
@@ -338,11 +364,14 @@
|
||||
}
|
||||
|
||||
// Kanban Record - Utility classes
|
||||
&.oe_kanban_global_click, &.oe_kanban_global_click_edit,
|
||||
.oe_kanban_global_click, .oe_kanban_global_click_edit {
|
||||
&.oe_kanban_global_click,
|
||||
&.oe_kanban_global_click_edit,
|
||||
.oe_kanban_global_click,
|
||||
.oe_kanban_global_click_edit {
|
||||
cursor: pointer;
|
||||
&:focus, &:focus-within {
|
||||
outline: thin solid mix(map-get($theme-colors, 'primary'), map-get($grays, '400'));
|
||||
&:focus,
|
||||
&:focus-within {
|
||||
outline: thin solid mix(map-get($theme-colors, "primary"), map-get($grays, "400"));
|
||||
outline-offset: -1px;
|
||||
}
|
||||
}
|
||||
@@ -382,7 +411,7 @@
|
||||
+ div {
|
||||
padding-left: $o-kanban-image-width + $o-kanban-inside-hgutter;
|
||||
@include media-breakpoint-down(md) {
|
||||
padding-left: $o-kanban-image-width + $o-kanban-inside-hgutter-mobile;
|
||||
padding-left: $o-kanban-image-width + $o-kanban-inside-hgutter-mobile;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -395,7 +424,7 @@
|
||||
min-width: 0;
|
||||
|
||||
ul {
|
||||
margin-bottom: $o-kanban-inner-hmargin*0.5;;
|
||||
margin-bottom: $o-kanban-inner-hmargin * 0.5;
|
||||
padding-left: 0;
|
||||
list-style: none;
|
||||
font-size: $font-size-sm;
|
||||
@@ -416,7 +445,7 @@
|
||||
}
|
||||
|
||||
.oe_kanban_text_red {
|
||||
color: #A61300;
|
||||
color: #a61300;
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
|
||||
@@ -442,20 +471,21 @@
|
||||
scroll-snap-type: x mandatory;
|
||||
}
|
||||
|
||||
.o_kanban_record, .o_kanban_quick_create {
|
||||
.o_kanban_record,
|
||||
.o_kanban_quick_create {
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&.o_kanban_small_column .o_kanban_group:not(.o_column_folded) {
|
||||
flex-basis: $o-kanban-small-record-width + 2*$o-kanban-group-padding;
|
||||
flex-basis: $o-kanban-small-record-width + 2 * $o-kanban-group-padding;
|
||||
}
|
||||
}
|
||||
|
||||
// Kanban Grouped Layout - Column default
|
||||
.o_kanban_group {
|
||||
flex: 0 0 $o-kanban-default-record-width + 2*$o-kanban-group-padding;
|
||||
flex: 0 0 $o-kanban-default-record-width + 2 * $o-kanban-group-padding;
|
||||
padding: 0 $o-kanban-group-padding $o-kanban-group-padding $o-kanban-group-padding;
|
||||
background-color: inherit;
|
||||
|
||||
@@ -475,10 +505,11 @@
|
||||
|
||||
.o_kanban_quick_add i {
|
||||
@include o-kanban-icon;
|
||||
margin-left: $o-kanban-inside-hgutter*2;
|
||||
margin-left: $o-kanban-inside-hgutter * 2;
|
||||
}
|
||||
|
||||
&:hover .o_kanban_config, .o_kanban_config.show {
|
||||
&:hover .o_kanban_config,
|
||||
.o_kanban_config.show {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
@@ -525,11 +556,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
> .o_kanban_record, .o_kanban_quick_add, .o_kanban_config, .o_kanban_load_more {
|
||||
display: none!important;
|
||||
> .o_kanban_record,
|
||||
.o_kanban_quick_add,
|
||||
.o_kanban_config,
|
||||
.o_kanban_load_more {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
&:hover, &.o_kanban_hover {
|
||||
&:hover,
|
||||
&.o_kanban_hover {
|
||||
.o_kanban_header_title {
|
||||
opacity: 1;
|
||||
}
|
||||
@@ -539,19 +574,19 @@
|
||||
|
||||
// Kanban Grouped Layout - "Create new column" column
|
||||
.o_column_quick_create {
|
||||
flex: 0 0 $o-kanban-small-record-width + 2*$o-kanban-group-padding;
|
||||
flex: 0 0 $o-kanban-small-record-width + 2 * $o-kanban-group-padding;
|
||||
|
||||
.o_quick_create_folded {
|
||||
cursor: pointer;
|
||||
padding: 12px 16px;
|
||||
white-space: nowrap;
|
||||
font-weight: $font-weight-bold;
|
||||
@include o-hover-opacity(.7);
|
||||
@include o-hover-opacity(0.7);
|
||||
@include o-hover-text-color($text-muted, $body-color);
|
||||
}
|
||||
|
||||
.o_quick_create_unfolded {
|
||||
margin: $border-width ($o-kanban-inside-hgutter * .5) 0;
|
||||
margin: $border-width ($o-kanban-inside-hgutter * 0.5) 0;
|
||||
padding: $o-kanban-inside-vgutter $o-kanban-inside-hgutter;
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
@@ -565,23 +600,25 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input, input:focus, input:hover {
|
||||
input,
|
||||
input:focus,
|
||||
input:hover {
|
||||
font-size: 16px;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.o_kanban_muted_record {
|
||||
background: map-get($grays, '300');
|
||||
background: map-get($grays, "300");
|
||||
height: 70px;
|
||||
margin: 10px 0px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
.o_kanban_group, .o_column_quick_create {
|
||||
.o_kanban_group,
|
||||
.o_column_quick_create {
|
||||
flex: 1 0 90%; // don't take full width to give a hint of next/previous column
|
||||
scroll-snap-align: center;
|
||||
overflow-y: scroll;
|
||||
@@ -622,7 +659,7 @@
|
||||
&.o_kanban_ghost {
|
||||
height: 0;
|
||||
border: none;
|
||||
min-height: 0!important; // to prevent view writers to override this height
|
||||
min-height: 0 !important; // to prevent view writers to override this height
|
||||
visibility: hidden;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
|
||||
@@ -51,6 +51,7 @@ export class KanbanRenderer extends Component {
|
||||
// Params
|
||||
ref: rootRef,
|
||||
elements: ".o_record_draggable",
|
||||
ignore: ".dropdown",
|
||||
groups: () => this.props.list.isGrouped && ".o_kanban_group",
|
||||
connectGroups: () => this.canMoveRecords,
|
||||
cursor: "move",
|
||||
|
||||
@@ -275,7 +275,7 @@ QUnit.module("UI", ({ beforeEach }) => {
|
||||
assert.ok(true, "No drag sequence should have been initiated");
|
||||
});
|
||||
|
||||
QUnit.test("Ignore specified elements elements", async (assert) => {
|
||||
QUnit.test("Ignore specified elements", async (assert) => {
|
||||
assert.expect(6);
|
||||
|
||||
class List extends Component {
|
||||
|
||||
Reference in New Issue
Block a user